Thanks to visit codestin.com
Credit goes to github.com

Skip to content

feat(language-core): type support of slot children #5137

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 21 commits into from
Mar 16, 2025

Conversation

KazariEX
Copy link
Member

@KazariEX KazariEX commented Jan 21, 2025

Resolves vuejs/rfcs#733

image

Copy link

pkg-pr-new bot commented Jan 21, 2025

Open in Stackblitz

vue-component-meta

npm i https://pkg.pr.new/vuejs/language-tools/vue-component-meta@5137

vue-component-type-helpers

npm i https://pkg.pr.new/vuejs/language-tools/vue-component-type-helpers@5137

@vue/language-core

npm i https://pkg.pr.new/vuejs/language-tools/@vue/language-core@5137

@vue/language-plugin-pug

npm i https://pkg.pr.new/vuejs/language-tools/@vue/language-plugin-pug@5137

@vue/language-server

npm i https://pkg.pr.new/vuejs/language-tools/@vue/language-server@5137

vue-tsc

npm i https://pkg.pr.new/vuejs/language-tools/vue-tsc@5137

@vue/language-service

npm i https://pkg.pr.new/vuejs/language-tools/@vue/language-service@5137

@vue/typescript-plugin

npm i https://pkg.pr.new/vuejs/language-tools/@vue/typescript-plugin@5137

commit: 4b9cfdc

@KazariEX KazariEX force-pushed the feat/typed-slot-children branch from 6201b84 to c0df03a Compare January 21, 2025 15:58
@KazariEX KazariEX force-pushed the master branch 2 times, most recently from 5ae4b38 to d782f70 Compare March 2, 2025 10:45
@KazariEX KazariEX force-pushed the feat/typed-slot-children branch from 11e1997 to d3b1c8a Compare March 16, 2025 20:00
@johnsoncodehk johnsoncodehk marked this pull request as ready for review March 16, 2025 20:48
@johnsoncodehk johnsoncodehk merged commit 4bde3e1 into vuejs:master Mar 16, 2025
6 checks passed
@KazariEX KazariEX deleted the feat/typed-slot-children branch March 17, 2025 07:10
@Anoesj
Copy link

Anoesj commented Jul 16, 2025

Awesome!!

@Anoesj
Copy link

Anoesj commented Jul 16, 2025

If only text content is expected in a slot, how would one type that? I tried numerous things:

const slots = defineSlots<{
  default?: () => HTMLElement;
}>();

const slots = defineSlots<{
  default?: () => Text;
}>();

const slots = defineSlots<{
  default?: () => string;
}>();

I tried all of these separately, but text content in a slot is typed as [], so all of these actually fail. Does [] indicate: no HTML elements or components? So is this the correct form? It works, but it does look a bit weird...

const slots = defineSlots<{
  default?: () => [];
}>();

@KazariEX
Copy link
Member Author

We currently do not generate virtual code for text nodes, so this cannot be type checked yet. You can indeed use [] to indicate that no native elements or components are accepted.

@Anoesj
Copy link

Anoesj commented Jul 16, 2025

Hmm that's too bad, because even though this is a very very welcome addition, it's not entirely strict that way. See, you can do this without getting any TS errors:

LoadingSpinner.vue

<template>
  <div class="loading-spinner">
    <slot><span>Loading...</span></slot>
  </div>
</template>

<script setup lang="ts">
  const slots = defineSlots<{
    default: () => [HTMLElement]
  }>();
</script>

dashboard.vue

<LoadingSpinner v-if="loading">
  <span></span>Loading dashboard...
</LoadingSpinner>

It's not the perfect example, but I think you understand what I mean. Strictly speaking, the slot children are wrong here, while the types state they're fine.

I also noticed that even though you state the slot children should be [HTMLSpanElement], it accepts any other html tag in there anyway. So you can't really narrow down what type of html elements can be used as slot children.


Probably also good if this new feature is documented a little more extensively on the Vue website. The new defineSlots syntax isn't documented yet either on vuejs.org, right now. Do you know if someone is working on that? I didn't read any announcements for this new syntax (which also seems to be available without strictSlotChildren: true) anywhere either.

This syntax is documented:

<script setup lang="ts">
const slots = defineSlots<{
  default(props: { msg: string }): any
}>()
</script>

This one isn't:

<script setup lang="ts">
const slots = defineSlots<{
  default: (props: { msg: string }) => [HTMLElement]
}>()
</script>

Sorry if I should have created issues instead of replying on your pull request!

@KazariEX
Copy link
Member Author

KazariEX commented Jul 16, 2025

After discussing with other members, we think that this feature is not yet perfect. We hope to eventually achieve an effect similar to renders in Flow, which requires cooperation with core. You can express your opinions on vuejs/rfcs#733 to promote the progress of this proposal.

@Anoesj
Copy link

Anoesj commented Jul 16, 2025

Oh I see! So it's experimental? Will the syntax change in the future? Because in that case, probably good to mention that in the Wiki too.

@KazariEX
Copy link
Member Author

You are right. I'll consider making this feature experimental for now.

@Anoesj
Copy link

Anoesj commented Jul 16, 2025

Thanks, good idea. By the way, as an outsider, it was not very clear what every vueCompilerOptions option does. Maybe some before/after code examples per option would help clarify what exactly every option does. Like, I tried inferComponentDollarRefs: true, but I really don't know what changed after turning it on.

It also seems like the deepwiki is outdated about this topic: https://deepwiki.com/vuejs/language-tools/2.2-typescript-integration#vue-compiler-options

@Anoesj
Copy link

Anoesj commented Jul 17, 2025

I cannot find out how to suggest changes to the wiki or make a PR for it, so I created a discussion for it here: #5509

Note that I'm still working on it, but accidentally submitted the discussion already (πŸ˜…), so I'll add more to it in the following hours.

KazariEX added a commit to KazariEX/vuejs-language-tools that referenced this pull request Jul 17, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants