-
Notifications
You must be signed in to change notification settings - Fork 1
dynamic slots are untyped #23
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
Comments
I think it is a upstream problem, the module has no affect to the generation of The issue should be tracked in mkdist or vuejs/language-tools Update: there was a fix vuejs/language-tools#5247 |
As for the reproduce, the playground not the correct way to use I have updated the playground, your reproduce should work fine in the new playground, feel free to reopen it if you found the output were not expected. updated reproduceimport { parse as parseSFC } from '@vue/compiler-sfc'
import { transform } from 'esbuild'
import { preTranspileScriptSetup, transpileVueTemplate } from 'vue-sfc-transformer'
const src = `
<script lang="ts">
export type DynamicSlots<
T extends { slot?: string },
S extends string | undefined = undefined,
D extends object = {}
> = {
[
K in NonNullable<T['slot']> as K extends string
? S extends undefined
? K
: (K | \`\${K}-\${S & string}\`)
: never
]: (props: {
item: Extract<T, { slot: S extends undefined
? K
: K extends \`\${infer Base}-\${S & string}\`
? Base
: K }>
} & D) => any
} & {
[key: string]: (props: { item: T } & D) => any
}
export interface Item {
label?: string
slot?: string
[key: string]: any
}
export type Slots<T extends Item = Item> = {
test: (props: { item: T, index: number }) => any
} & DynamicSlots<T, undefined, { index: number }>
</script>
<script setup lang="ts" generic="T extends Item">
defineProps<{
items: T[]
}>()
defineSlots<Slots<T>>()
</script>
<template>
<div v-if="(items as any)">
{{ items }}
</div>
</template>
`
const sfc = parseSFC(src, {
filename: 'test.vue',
ignoreEmpty: true,
})
// transpile template block
const templateBlockContents = await transpileVueTemplate(
sfc.descriptor.template.content,
sfc.descriptor.template.ast,
sfc.descriptor.template.loc.start.offset,
async (code) => {
const res = await transform(code, { loader: 'ts', target: 'esnext' })
return res.code
},
)
console.log(`transpiled <template> block:`)
console.log(`\`\`\`\n<template>${templateBlockContents}</template>\n\`\`\`\n`)
// transpile script block
// notice: it is still in typescript, you need to transpile it to javascript later
const { content: scriptBlockContents } = await preTranspileScriptSetup(sfc.descriptor, 'test.vue')
console.log(`transpiled <script setup> block:`)
console.log(`\`\`\`\n<script setup lang="ts">${scriptBlockContents}</script>\n\`\`\`\n`) output:
|
Makes sense. Will dig into it a bit more, thanks! |
🐛 The bug
We found another bug while working on Nuxt UI, and this one is even harder to provide a native
vue-sfc-transformer
reproduction (in fact I'm not even able to make the linked one run at all).Nuxt UI has a number of components that other than static slots (eg:
label
,content
,leading
, etc..) also provides dynamic slots, meaning that you can directly access a specific item in your input array.For example using
UTabs
:but once parsed with
vue-sfc-transformer
it no longer works, anditem
falls back to the defaultTabsItem
type (screenshot from an actual project installing@nuxt/ui
)🛠️ To reproduce
https://stackblitz.com/edit/github-sadsa3hd?file=index.js
🌈 Expected behaviour
should provide the following auto-complete and correctly type
item
(these screenshots are from within the@nuxt/ui
playground)ℹ️ Additional context
I'm not using the latest
@nuxt/ui
release as I was fixing other stuff related to dynamic slots, please use the latest CIhttps://pkg.pr.new/@nuxt/ui@9817465
(coming from nuxt/ui#3857)I also tried directly accessing the types and they do seem to work (screenshot from an actual project installing

@nuxt/ui
)src
TabsSlots
typeDynamicSlots
utilitycurrently generated
Tabs.vue.d.ts
The text was updated successfully, but these errors were encountered: