-
-
Notifications
You must be signed in to change notification settings - Fork 481
Description
I swear this used to work ages ago.
Vuetify defines slots as $props.$children
and sets JSX.ElementChildrenAttribute
to $children
. Vue already comes with JSX.ElementAttributesProperty
as $props
so this works great in JSX:
// import { VMenu } from 'vuetify/components'
import type { DefineComponent, VNodeChild } from 'vue'
declare const VMenu: DefineComponent<{
$children: {
activator: (props: { isActive: boolean }) => VNodeChild
}
}>
const el = (
<VMenu>
{{ activator: props => String(props.isActive) }}
</VMenu>
)
Volar is only looking at $slots
or children
though, so we'd have to define our slot types twice for them to work with it.
language-tools/packages/vue-language-core/src/utils/localTypes.ts
Lines 61 to 65 in 97b01e6
export type ExtractComponentSlots<T> = | |
IsAny<T> extends true ? Record<string, any> | |
: T extends { ${slots}?: infer S } ? { [K in keyof S]-?: S[K] extends ((obj: infer O) => any) | undefined ? O : any } | |
: T extends { children?: infer S } ? { [K in keyof S]-?: S[K] extends ((obj: infer O) => any) | undefined ? O : any } | |
: Record<string, any>; |
This also means that slots from .vue files only work in other .vue files and can't be used in JSX:
<script setup lang="ts"></script>
<template>
<slot name="activator" :isActive="false" />
</template>
import Slots from './Slots.vue'
const el = (
<Slots>
{{ foo: props => props.isActive }} // expected boolean, got implicit any
</Slots>
)
vuejs/core#7083 adds ElementChildrenAttribute to vue core.
Volar could check T[keyof JSX.ElementAttributesProperty][keyof JSX.ElementChildrenAttribute]
to support any combination of these, and generate its own slots in $props
somewhere so they can be used in JSX.