mirror of https://github.com/vuejs/core.git
feat(types/slots): support slot presence / props type checks via `defineSlots` macro and `slots` option (#7982)
This commit is contained in:
parent
59e828448e
commit
5a2f5d59cf
|
@ -1785,6 +1785,51 @@ return { props, emit }
|
||||||
})"
|
})"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`SFC compile <script setup> > with TypeScript > defineSlots() > basic usage 1`] = `
|
||||||
|
"import { useSlots as _useSlots, defineComponent as _defineComponent } from 'vue'
|
||||||
|
|
||||||
|
export default /*#__PURE__*/_defineComponent({
|
||||||
|
setup(__props, { expose: __expose }) {
|
||||||
|
__expose();
|
||||||
|
|
||||||
|
const slots = _useSlots()
|
||||||
|
|
||||||
|
return { slots }
|
||||||
|
}
|
||||||
|
|
||||||
|
})"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`SFC compile <script setup> > with TypeScript > defineSlots() > w/o generic params 1`] = `
|
||||||
|
"import { useSlots as _useSlots } from 'vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
setup(__props, { expose: __expose }) {
|
||||||
|
__expose();
|
||||||
|
|
||||||
|
const slots = _useSlots()
|
||||||
|
|
||||||
|
return { slots }
|
||||||
|
}
|
||||||
|
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`SFC compile <script setup> > with TypeScript > defineSlots() > w/o return value 1`] = `
|
||||||
|
"import { defineComponent as _defineComponent } from 'vue'
|
||||||
|
|
||||||
|
export default /*#__PURE__*/_defineComponent({
|
||||||
|
setup(__props, { expose: __expose }) {
|
||||||
|
__expose();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return { }
|
||||||
|
}
|
||||||
|
|
||||||
|
})"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`SFC compile <script setup> > with TypeScript > hoist type declarations 1`] = `
|
exports[`SFC compile <script setup> > with TypeScript > hoist type declarations 1`] = `
|
||||||
"import { defineComponent as _defineComponent } from 'vue'
|
"import { defineComponent as _defineComponent } from 'vue'
|
||||||
export interface Foo {}
|
export interface Foo {}
|
||||||
|
|
|
@ -1585,6 +1585,45 @@ const emit = defineEmits(['a', 'b'])
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('defineSlots()', () => {
|
||||||
|
test('basic usage', () => {
|
||||||
|
const { content } = compile(`
|
||||||
|
<script setup lang="ts">
|
||||||
|
const slots = defineSlots<{
|
||||||
|
default: { msg: string }
|
||||||
|
}>()
|
||||||
|
</script>
|
||||||
|
`)
|
||||||
|
assertCode(content)
|
||||||
|
expect(content).toMatch(`const slots = _useSlots()`)
|
||||||
|
expect(content).not.toMatch('defineSlots')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('w/o return value', () => {
|
||||||
|
const { content } = compile(`
|
||||||
|
<script setup lang="ts">
|
||||||
|
defineSlots<{
|
||||||
|
default: { msg: string }
|
||||||
|
}>()
|
||||||
|
</script>
|
||||||
|
`)
|
||||||
|
assertCode(content)
|
||||||
|
expect(content).not.toMatch('defineSlots')
|
||||||
|
expect(content).not.toMatch(`_useSlots`)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('w/o generic params', () => {
|
||||||
|
const { content } = compile(`
|
||||||
|
<script setup>
|
||||||
|
const slots = defineSlots()
|
||||||
|
</script>
|
||||||
|
`)
|
||||||
|
assertCode(content)
|
||||||
|
expect(content).toMatch(`const slots = _useSlots()`)
|
||||||
|
expect(content).not.toMatch('defineSlots')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
test('runtime Enum', () => {
|
test('runtime Enum', () => {
|
||||||
const { content, bindings } = compile(
|
const { content, bindings } = compile(
|
||||||
`<script setup lang="ts">
|
`<script setup lang="ts">
|
||||||
|
|
|
@ -67,6 +67,7 @@ const DEFINE_EMITS = 'defineEmits'
|
||||||
const DEFINE_EXPOSE = 'defineExpose'
|
const DEFINE_EXPOSE = 'defineExpose'
|
||||||
const WITH_DEFAULTS = 'withDefaults'
|
const WITH_DEFAULTS = 'withDefaults'
|
||||||
const DEFINE_OPTIONS = 'defineOptions'
|
const DEFINE_OPTIONS = 'defineOptions'
|
||||||
|
const DEFINE_SLOTS = 'defineSlots'
|
||||||
|
|
||||||
const isBuiltInDir = makeMap(
|
const isBuiltInDir = makeMap(
|
||||||
`once,memo,if,for,else,else-if,slot,text,html,on,bind,model,show,cloak,is`
|
`once,memo,if,for,else,else-if,slot,text,html,on,bind,model,show,cloak,is`
|
||||||
|
@ -312,6 +313,7 @@ export function compileScript(
|
||||||
let hasDefaultExportName = false
|
let hasDefaultExportName = false
|
||||||
let hasDefaultExportRender = false
|
let hasDefaultExportRender = false
|
||||||
let hasDefineOptionsCall = false
|
let hasDefineOptionsCall = false
|
||||||
|
let hasDefineSlotsCall = false
|
||||||
let propsRuntimeDecl: Node | undefined
|
let propsRuntimeDecl: Node | undefined
|
||||||
let propsRuntimeDefaults: Node | undefined
|
let propsRuntimeDefaults: Node | undefined
|
||||||
let propsDestructureDecl: Node | undefined
|
let propsDestructureDecl: Node | undefined
|
||||||
|
@ -590,6 +592,30 @@ export function compileScript(
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function processDefineSlots(node: Node, declId?: LVal): boolean {
|
||||||
|
if (!isCallOf(node, DEFINE_SLOTS)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (hasDefineSlotsCall) {
|
||||||
|
error(`duplicate ${DEFINE_SLOTS}() call`, node)
|
||||||
|
}
|
||||||
|
hasDefineSlotsCall = true
|
||||||
|
|
||||||
|
if (node.arguments.length > 0) {
|
||||||
|
error(`${DEFINE_SLOTS}() cannot accept arguments`, node)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (declId) {
|
||||||
|
s.overwrite(
|
||||||
|
startOffset + node.start!,
|
||||||
|
startOffset + node.end!,
|
||||||
|
`${helper('useSlots')}()`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
function getAstBody(): Statement[] {
|
function getAstBody(): Statement[] {
|
||||||
return scriptAst
|
return scriptAst
|
||||||
? [...scriptSetupAst.body, ...scriptAst.body]
|
? [...scriptSetupAst.body, ...scriptAst.body]
|
||||||
|
@ -683,6 +709,7 @@ export function compileScript(
|
||||||
let propsOption = undefined
|
let propsOption = undefined
|
||||||
let emitsOption = undefined
|
let emitsOption = undefined
|
||||||
let exposeOption = undefined
|
let exposeOption = undefined
|
||||||
|
let slotsOption = undefined
|
||||||
if (optionsRuntimeDecl.type === 'ObjectExpression') {
|
if (optionsRuntimeDecl.type === 'ObjectExpression') {
|
||||||
for (const prop of optionsRuntimeDecl.properties) {
|
for (const prop of optionsRuntimeDecl.properties) {
|
||||||
if (
|
if (
|
||||||
|
@ -692,6 +719,7 @@ export function compileScript(
|
||||||
if (prop.key.name === 'props') propsOption = prop
|
if (prop.key.name === 'props') propsOption = prop
|
||||||
if (prop.key.name === 'emits') emitsOption = prop
|
if (prop.key.name === 'emits') emitsOption = prop
|
||||||
if (prop.key.name === 'expose') exposeOption = prop
|
if (prop.key.name === 'expose') exposeOption = prop
|
||||||
|
if (prop.key.name === 'slots') slotsOption = prop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -714,6 +742,12 @@ export function compileScript(
|
||||||
exposeOption
|
exposeOption
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
if (slotsOption) {
|
||||||
|
error(
|
||||||
|
`${DEFINE_OPTIONS}() cannot be used to declare slots. Use ${DEFINE_SLOTS}() instead.`,
|
||||||
|
slotsOption
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -1286,7 +1320,8 @@ export function compileScript(
|
||||||
processDefineProps(expr) ||
|
processDefineProps(expr) ||
|
||||||
processDefineEmits(expr) ||
|
processDefineEmits(expr) ||
|
||||||
processDefineOptions(expr) ||
|
processDefineOptions(expr) ||
|
||||||
processWithDefaults(expr)
|
processWithDefaults(expr) ||
|
||||||
|
processDefineSlots(expr)
|
||||||
) {
|
) {
|
||||||
s.remove(node.start! + startOffset, node.end! + startOffset)
|
s.remove(node.start! + startOffset, node.end! + startOffset)
|
||||||
} else if (processDefineExpose(expr)) {
|
} else if (processDefineExpose(expr)) {
|
||||||
|
@ -1320,7 +1355,10 @@ export function compileScript(
|
||||||
const isDefineProps =
|
const isDefineProps =
|
||||||
processDefineProps(init, decl.id) ||
|
processDefineProps(init, decl.id) ||
|
||||||
processWithDefaults(init, decl.id)
|
processWithDefaults(init, decl.id)
|
||||||
const isDefineEmits = processDefineEmits(init, decl.id)
|
const isDefineEmits =
|
||||||
|
!isDefineProps && processDefineEmits(init, decl.id)
|
||||||
|
!isDefineEmits && processDefineSlots(init, decl.id)
|
||||||
|
|
||||||
if (isDefineProps || isDefineEmits) {
|
if (isDefineProps || isDefineEmits) {
|
||||||
if (left === 1) {
|
if (left === 1) {
|
||||||
s.remove(node.start! + startOffset, node.end! + startOffset)
|
s.remove(node.start! + startOffset, node.end! + startOffset)
|
||||||
|
|
|
@ -8,7 +8,10 @@ import {
|
||||||
ComponentPublicInstance,
|
ComponentPublicInstance,
|
||||||
ComponentOptions,
|
ComponentOptions,
|
||||||
SetupContext,
|
SetupContext,
|
||||||
h
|
h,
|
||||||
|
SlotsType,
|
||||||
|
Slots,
|
||||||
|
VNode
|
||||||
} from 'vue'
|
} from 'vue'
|
||||||
import { describe, expectType, IsUnion } from './utils'
|
import { describe, expectType, IsUnion } from './utils'
|
||||||
|
|
||||||
|
@ -1406,6 +1409,69 @@ export default {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
describe('slots', () => {
|
||||||
|
const comp1 = defineComponent({
|
||||||
|
slots: Object as SlotsType<{
|
||||||
|
default: { foo: string; bar: number }
|
||||||
|
optional?: { data: string }
|
||||||
|
undefinedScope: undefined | { data: string }
|
||||||
|
optionalUndefinedScope?: undefined | { data: string }
|
||||||
|
}>,
|
||||||
|
setup(props, { slots }) {
|
||||||
|
expectType<(scope: { foo: string; bar: number }) => VNode[]>(
|
||||||
|
slots.default
|
||||||
|
)
|
||||||
|
expectType<((scope: { data: string }) => VNode[]) | undefined>(
|
||||||
|
slots.optional
|
||||||
|
)
|
||||||
|
|
||||||
|
slots.default({ foo: 'foo', bar: 1 })
|
||||||
|
|
||||||
|
// @ts-expect-error it's optional
|
||||||
|
slots.optional({ data: 'foo' })
|
||||||
|
slots.optional?.({ data: 'foo' })
|
||||||
|
|
||||||
|
expectType<{
|
||||||
|
(): VNode[]
|
||||||
|
(scope: undefined | { data: string }): VNode[]
|
||||||
|
}>(slots.undefinedScope)
|
||||||
|
|
||||||
|
expectType<
|
||||||
|
| { (): VNode[]; (scope: undefined | { data: string }): VNode[] }
|
||||||
|
| undefined
|
||||||
|
>(slots.optionalUndefinedScope)
|
||||||
|
|
||||||
|
slots.default({ foo: 'foo', bar: 1 })
|
||||||
|
// @ts-expect-error it's optional
|
||||||
|
slots.optional({ data: 'foo' })
|
||||||
|
slots.optional?.({ data: 'foo' })
|
||||||
|
slots.undefinedScope()
|
||||||
|
slots.undefinedScope(undefined)
|
||||||
|
// @ts-expect-error
|
||||||
|
slots.undefinedScope('foo')
|
||||||
|
|
||||||
|
slots.optionalUndefinedScope?.()
|
||||||
|
slots.optionalUndefinedScope?.(undefined)
|
||||||
|
slots.optionalUndefinedScope?.({ data: 'foo' })
|
||||||
|
// @ts-expect-error
|
||||||
|
slots.optionalUndefinedScope()
|
||||||
|
// @ts-expect-error
|
||||||
|
slots.optionalUndefinedScope?.('foo')
|
||||||
|
|
||||||
|
expectType<typeof slots | undefined>(new comp1().$slots)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const comp2 = defineComponent({
|
||||||
|
setup(props, { slots }) {
|
||||||
|
// unknown slots
|
||||||
|
expectType<Slots>(slots)
|
||||||
|
expectType<((...args: any[]) => VNode[]) | undefined>(slots.default)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
expectType<Slots | undefined>(new comp2().$slots)
|
||||||
|
})
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DefineComponent,
|
DefineComponent,
|
||||||
ComponentOptionsMixin,
|
ComponentOptionsMixin,
|
||||||
|
@ -1428,6 +1494,7 @@ declare const MyButton: DefineComponent<
|
||||||
ComponentOptionsMixin,
|
ComponentOptionsMixin,
|
||||||
EmitsOptions,
|
EmitsOptions,
|
||||||
string,
|
string,
|
||||||
|
{},
|
||||||
VNodeProps & AllowedComponentProps & ComponentCustomProps,
|
VNodeProps & AllowedComponentProps & ComponentCustomProps,
|
||||||
Readonly<ExtractPropTypes<{}>>,
|
Readonly<ExtractPropTypes<{}>>,
|
||||||
{}
|
{}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { h, Text, FunctionalComponent, Component } from 'vue'
|
import { h, Text, FunctionalComponent, Component, VNode } from 'vue'
|
||||||
import { expectType } from './utils'
|
import { expectType } from './utils'
|
||||||
|
|
||||||
// simple function signature
|
// simple function signature
|
||||||
|
@ -68,3 +68,29 @@ const Qux: FunctionalComponent<{}, ['foo', 'bar']> = (props, { emit }) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
expectType<Component>(Qux)
|
expectType<Component>(Qux)
|
||||||
|
|
||||||
|
const Quux: FunctionalComponent<
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
default: { foo: number }
|
||||||
|
optional?: { foo: number }
|
||||||
|
}
|
||||||
|
> = (props, { emit, slots }) => {
|
||||||
|
expectType<{
|
||||||
|
default: (scope: { foo: number }) => VNode[]
|
||||||
|
optional?: (scope: { foo: number }) => VNode[]
|
||||||
|
}>(slots)
|
||||||
|
|
||||||
|
slots.default({ foo: 123 })
|
||||||
|
// @ts-expect-error
|
||||||
|
slots.default({ foo: 'fesf' })
|
||||||
|
|
||||||
|
slots.optional?.({ foo: 123 })
|
||||||
|
// @ts-expect-error
|
||||||
|
slots.optional?.({ foo: 'fesf' })
|
||||||
|
// @ts-expect-error
|
||||||
|
slots.optional({ foo: 123 })
|
||||||
|
}
|
||||||
|
expectType<Component>(Quux)
|
||||||
|
;<Quux />
|
||||||
|
|
|
@ -4,7 +4,9 @@ import {
|
||||||
useAttrs,
|
useAttrs,
|
||||||
useSlots,
|
useSlots,
|
||||||
withDefaults,
|
withDefaults,
|
||||||
Slots
|
Slots,
|
||||||
|
defineSlots,
|
||||||
|
VNode
|
||||||
} from 'vue'
|
} from 'vue'
|
||||||
import { describe, expectType } from './utils'
|
import { describe, expectType } from './utils'
|
||||||
|
|
||||||
|
@ -179,6 +181,27 @@ describe('defineEmits w/ runtime declaration', () => {
|
||||||
emit2('baz')
|
emit2('baz')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('defineSlots', () => {
|
||||||
|
// short syntax
|
||||||
|
const slots = defineSlots<{
|
||||||
|
default: { foo: string; bar: number }
|
||||||
|
optional?: string
|
||||||
|
}>()
|
||||||
|
expectType<(scope: { foo: string; bar: number }) => VNode[]>(slots.default)
|
||||||
|
expectType<undefined | ((scope: string) => VNode[])>(slots.optional)
|
||||||
|
|
||||||
|
// literal fn syntax (allow for specifying return type)
|
||||||
|
const fnSlots = defineSlots<{
|
||||||
|
default(props: { foo: string; bar: number }): any
|
||||||
|
optional?(props: string): any
|
||||||
|
}>()
|
||||||
|
expectType<(scope: { foo: string; bar: number }) => VNode[]>(fnSlots.default)
|
||||||
|
expectType<undefined | ((scope: string) => VNode[])>(fnSlots.optional)
|
||||||
|
|
||||||
|
const slotsUntype = defineSlots()
|
||||||
|
expectType<Slots>(slotsUntype)
|
||||||
|
})
|
||||||
|
|
||||||
describe('useAttrs', () => {
|
describe('useAttrs', () => {
|
||||||
const attrs = useAttrs()
|
const attrs = useAttrs()
|
||||||
expectType<Record<string, unknown>>(attrs)
|
expectType<Record<string, unknown>>(attrs)
|
||||||
|
|
|
@ -28,6 +28,7 @@ import {
|
||||||
CreateComponentPublicInstance,
|
CreateComponentPublicInstance,
|
||||||
ComponentPublicInstanceConstructor
|
ComponentPublicInstanceConstructor
|
||||||
} from './componentPublicInstance'
|
} from './componentPublicInstance'
|
||||||
|
import { SlotsType } from './componentSlots'
|
||||||
|
|
||||||
export type PublicProps = VNodeProps &
|
export type PublicProps = VNodeProps &
|
||||||
AllowedComponentProps &
|
AllowedComponentProps &
|
||||||
|
@ -43,6 +44,7 @@ export type DefineComponent<
|
||||||
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
|
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
|
||||||
E extends EmitsOptions = {},
|
E extends EmitsOptions = {},
|
||||||
EE extends string = string,
|
EE extends string = string,
|
||||||
|
S extends SlotsType = {},
|
||||||
PP = PublicProps,
|
PP = PublicProps,
|
||||||
Props = Readonly<
|
Props = Readonly<
|
||||||
PropsOrPropOptions extends ComponentPropsOptions
|
PropsOrPropOptions extends ComponentPropsOptions
|
||||||
|
@ -61,6 +63,7 @@ export type DefineComponent<
|
||||||
Mixin,
|
Mixin,
|
||||||
Extends,
|
Extends,
|
||||||
E,
|
E,
|
||||||
|
S,
|
||||||
PP & Props,
|
PP & Props,
|
||||||
Defaults,
|
Defaults,
|
||||||
true
|
true
|
||||||
|
@ -77,6 +80,7 @@ export type DefineComponent<
|
||||||
Extends,
|
Extends,
|
||||||
E,
|
E,
|
||||||
EE,
|
EE,
|
||||||
|
S,
|
||||||
Defaults
|
Defaults
|
||||||
> &
|
> &
|
||||||
PP
|
PP
|
||||||
|
@ -91,29 +95,33 @@ export type DefineComponent<
|
||||||
export function defineComponent<
|
export function defineComponent<
|
||||||
Props extends Record<string, any>,
|
Props extends Record<string, any>,
|
||||||
E extends EmitsOptions = {},
|
E extends EmitsOptions = {},
|
||||||
EE extends string = string
|
EE extends string = string,
|
||||||
|
S extends SlotsType = {}
|
||||||
>(
|
>(
|
||||||
setup: (
|
setup: (
|
||||||
props: Props,
|
props: Props,
|
||||||
ctx: SetupContext<E>
|
ctx: SetupContext<E, S>
|
||||||
) => RenderFunction | Promise<RenderFunction>,
|
) => RenderFunction | Promise<RenderFunction>,
|
||||||
options?: Pick<ComponentOptions, 'name' | 'inheritAttrs'> & {
|
options?: Pick<ComponentOptions, 'name' | 'inheritAttrs'> & {
|
||||||
props?: (keyof Props)[]
|
props?: (keyof Props)[]
|
||||||
emits?: E | EE[]
|
emits?: E | EE[]
|
||||||
|
slots?: S
|
||||||
}
|
}
|
||||||
): (props: Props & EmitsToProps<E>) => any
|
): (props: Props & EmitsToProps<E>) => any
|
||||||
export function defineComponent<
|
export function defineComponent<
|
||||||
Props extends Record<string, any>,
|
Props extends Record<string, any>,
|
||||||
E extends EmitsOptions = {},
|
E extends EmitsOptions = {},
|
||||||
EE extends string = string
|
EE extends string = string,
|
||||||
|
S extends SlotsType = {}
|
||||||
>(
|
>(
|
||||||
setup: (
|
setup: (
|
||||||
props: Props,
|
props: Props,
|
||||||
ctx: SetupContext<E>
|
ctx: SetupContext<E, S>
|
||||||
) => RenderFunction | Promise<RenderFunction>,
|
) => RenderFunction | Promise<RenderFunction>,
|
||||||
options?: Pick<ComponentOptions, 'name' | 'inheritAttrs'> & {
|
options?: Pick<ComponentOptions, 'name' | 'inheritAttrs'> & {
|
||||||
props?: ComponentObjectPropsOptions<Props>
|
props?: ComponentObjectPropsOptions<Props>
|
||||||
emits?: E | EE[]
|
emits?: E | EE[]
|
||||||
|
slots?: S
|
||||||
}
|
}
|
||||||
): (props: Props & EmitsToProps<E>) => any
|
): (props: Props & EmitsToProps<E>) => any
|
||||||
|
|
||||||
|
@ -130,6 +138,7 @@ export function defineComponent<
|
||||||
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
|
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
|
||||||
E extends EmitsOptions = {},
|
E extends EmitsOptions = {},
|
||||||
EE extends string = string,
|
EE extends string = string,
|
||||||
|
S extends SlotsType = {},
|
||||||
I extends ComponentInjectOptions = {},
|
I extends ComponentInjectOptions = {},
|
||||||
II extends string = string
|
II extends string = string
|
||||||
>(
|
>(
|
||||||
|
@ -143,10 +152,11 @@ export function defineComponent<
|
||||||
Extends,
|
Extends,
|
||||||
E,
|
E,
|
||||||
EE,
|
EE,
|
||||||
|
S,
|
||||||
I,
|
I,
|
||||||
II
|
II
|
||||||
>
|
>
|
||||||
): DefineComponent<Props, RawBindings, D, C, M, Mixin, Extends, E, EE>
|
): DefineComponent<Props, RawBindings, D, C, M, Mixin, Extends, E, EE, S>
|
||||||
|
|
||||||
// overload 3: object format with array props declaration
|
// overload 3: object format with array props declaration
|
||||||
// props inferred as { [key in PropNames]?: any }
|
// props inferred as { [key in PropNames]?: any }
|
||||||
|
@ -161,6 +171,7 @@ export function defineComponent<
|
||||||
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
|
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
|
||||||
E extends EmitsOptions = {},
|
E extends EmitsOptions = {},
|
||||||
EE extends string = string,
|
EE extends string = string,
|
||||||
|
S extends SlotsType = {},
|
||||||
I extends ComponentInjectOptions = {},
|
I extends ComponentInjectOptions = {},
|
||||||
II extends string = string
|
II extends string = string
|
||||||
>(
|
>(
|
||||||
|
@ -174,6 +185,7 @@ export function defineComponent<
|
||||||
Extends,
|
Extends,
|
||||||
E,
|
E,
|
||||||
EE,
|
EE,
|
||||||
|
S,
|
||||||
I,
|
I,
|
||||||
II
|
II
|
||||||
>
|
>
|
||||||
|
@ -186,7 +198,8 @@ export function defineComponent<
|
||||||
Mixin,
|
Mixin,
|
||||||
Extends,
|
Extends,
|
||||||
E,
|
E,
|
||||||
EE
|
EE,
|
||||||
|
S
|
||||||
>
|
>
|
||||||
|
|
||||||
// overload 4: object format with object props declaration
|
// overload 4: object format with object props declaration
|
||||||
|
@ -203,6 +216,7 @@ export function defineComponent<
|
||||||
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
|
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
|
||||||
E extends EmitsOptions = {},
|
E extends EmitsOptions = {},
|
||||||
EE extends string = string,
|
EE extends string = string,
|
||||||
|
S extends SlotsType = {},
|
||||||
I extends ComponentInjectOptions = {},
|
I extends ComponentInjectOptions = {},
|
||||||
II extends string = string
|
II extends string = string
|
||||||
>(
|
>(
|
||||||
|
@ -216,10 +230,11 @@ export function defineComponent<
|
||||||
Extends,
|
Extends,
|
||||||
E,
|
E,
|
||||||
EE,
|
EE,
|
||||||
|
S,
|
||||||
I,
|
I,
|
||||||
II
|
II
|
||||||
>
|
>
|
||||||
): DefineComponent<PropsOptions, RawBindings, D, C, M, Mixin, Extends, E, EE>
|
): DefineComponent<PropsOptions, RawBindings, D, C, M, Mixin, Extends, E, EE, S>
|
||||||
|
|
||||||
// implementation, close to no-op
|
// implementation, close to no-op
|
||||||
export function defineComponent(
|
export function defineComponent(
|
||||||
|
|
|
@ -25,6 +25,7 @@ import {
|
||||||
ExtractPropTypes
|
ExtractPropTypes
|
||||||
} from './componentProps'
|
} from './componentProps'
|
||||||
import { warn } from './warning'
|
import { warn } from './warning'
|
||||||
|
import { SlotsType, TypedSlots } from './componentSlots'
|
||||||
|
|
||||||
// dev only
|
// dev only
|
||||||
const warnRuntimeUsage = (method: string) =>
|
const warnRuntimeUsage = (method: string) =>
|
||||||
|
@ -184,9 +185,7 @@ export function defineOptions<
|
||||||
C extends ComputedOptions = {},
|
C extends ComputedOptions = {},
|
||||||
M extends MethodOptions = {},
|
M extends MethodOptions = {},
|
||||||
Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
|
Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
|
||||||
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
|
Extends extends ComponentOptionsMixin = ComponentOptionsMixin
|
||||||
E extends EmitsOptions = EmitsOptions,
|
|
||||||
EE extends string = string
|
|
||||||
>(
|
>(
|
||||||
options?: ComponentOptionsWithoutProps<
|
options?: ComponentOptionsWithoutProps<
|
||||||
{},
|
{},
|
||||||
|
@ -195,16 +194,23 @@ export function defineOptions<
|
||||||
C,
|
C,
|
||||||
M,
|
M,
|
||||||
Mixin,
|
Mixin,
|
||||||
Extends,
|
Extends
|
||||||
E,
|
> & { emits?: undefined; expose?: undefined; slots?: undefined }
|
||||||
EE
|
|
||||||
> & { emits?: undefined; expose?: undefined }
|
|
||||||
): void {
|
): void {
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
warnRuntimeUsage(`defineOptions`)
|
warnRuntimeUsage(`defineOptions`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function defineSlots<
|
||||||
|
S extends Record<string, any> = Record<string, any>
|
||||||
|
>(): // @ts-expect-error
|
||||||
|
TypedSlots<SlotsType<S>> {
|
||||||
|
if (__DEV__) {
|
||||||
|
warnRuntimeUsage(`defineSlots`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type NotUndefined<T> = T extends undefined ? never : T
|
type NotUndefined<T> = T extends undefined ? never : T
|
||||||
|
|
||||||
type InferDefaults<T> = {
|
type InferDefaults<T> = {
|
||||||
|
|
|
@ -27,7 +27,13 @@ import {
|
||||||
initProps,
|
initProps,
|
||||||
normalizePropsOptions
|
normalizePropsOptions
|
||||||
} from './componentProps'
|
} from './componentProps'
|
||||||
import { Slots, initSlots, InternalSlots } from './componentSlots'
|
import {
|
||||||
|
initSlots,
|
||||||
|
InternalSlots,
|
||||||
|
Slots,
|
||||||
|
SlotsType,
|
||||||
|
TypedSlots
|
||||||
|
} from './componentSlots'
|
||||||
import { warn } from './warning'
|
import { warn } from './warning'
|
||||||
import { ErrorCodes, callWithErrorHandling, handleError } from './errorHandling'
|
import { ErrorCodes, callWithErrorHandling, handleError } from './errorHandling'
|
||||||
import { AppContext, createAppContext, AppConfig } from './apiCreateApp'
|
import { AppContext, createAppContext, AppConfig } from './apiCreateApp'
|
||||||
|
@ -57,7 +63,8 @@ import {
|
||||||
isPromise,
|
isPromise,
|
||||||
ShapeFlags,
|
ShapeFlags,
|
||||||
extend,
|
extend,
|
||||||
getGlobalThis
|
getGlobalThis,
|
||||||
|
IfAny
|
||||||
} from '@vue/shared'
|
} from '@vue/shared'
|
||||||
import { SuspenseBoundary } from './components/Suspense'
|
import { SuspenseBoundary } from './components/Suspense'
|
||||||
import { CompilerOptions } from '@vue/compiler-core'
|
import { CompilerOptions } from '@vue/compiler-core'
|
||||||
|
@ -117,12 +124,19 @@ export interface ComponentInternalOptions {
|
||||||
__name?: string
|
__name?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FunctionalComponent<P = {}, E extends EmitsOptions = {}>
|
export interface FunctionalComponent<
|
||||||
extends ComponentInternalOptions {
|
P = {},
|
||||||
|
E extends EmitsOptions = {},
|
||||||
|
S extends Record<string, any> = any
|
||||||
|
> extends ComponentInternalOptions {
|
||||||
// use of any here is intentional so it can be a valid JSX Element constructor
|
// use of any here is intentional so it can be a valid JSX Element constructor
|
||||||
(props: P, ctx: Omit<SetupContext<E>, 'expose'>): any
|
(
|
||||||
|
props: P,
|
||||||
|
ctx: Omit<SetupContext<E, IfAny<S, {}, SlotsType<S>>>, 'expose'>
|
||||||
|
): any
|
||||||
props?: ComponentPropsOptions<P>
|
props?: ComponentPropsOptions<P>
|
||||||
emits?: E | (keyof E)[]
|
emits?: E | (keyof E)[]
|
||||||
|
slots?: IfAny<S, Slots, SlotsType<S>>
|
||||||
inheritAttrs?: boolean
|
inheritAttrs?: boolean
|
||||||
displayName?: string
|
displayName?: string
|
||||||
compatConfig?: CompatConfig
|
compatConfig?: CompatConfig
|
||||||
|
@ -147,7 +161,7 @@ export type ConcreteComponent<
|
||||||
M extends MethodOptions = MethodOptions
|
M extends MethodOptions = MethodOptions
|
||||||
> =
|
> =
|
||||||
| ComponentOptions<Props, RawBindings, D, C, M>
|
| ComponentOptions<Props, RawBindings, D, C, M>
|
||||||
| FunctionalComponent<Props, any>
|
| FunctionalComponent<Props, any, any>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A type used in public APIs where a component type is expected.
|
* A type used in public APIs where a component type is expected.
|
||||||
|
@ -168,10 +182,13 @@ export type { ComponentOptions }
|
||||||
type LifecycleHook<TFn = Function> = TFn[] | null
|
type LifecycleHook<TFn = Function> = TFn[] | null
|
||||||
|
|
||||||
// use `E extends any` to force evaluating type to fix #2362
|
// use `E extends any` to force evaluating type to fix #2362
|
||||||
export type SetupContext<E = EmitsOptions> = E extends any
|
export type SetupContext<
|
||||||
|
E = EmitsOptions,
|
||||||
|
S extends SlotsType = {}
|
||||||
|
> = E extends any
|
||||||
? {
|
? {
|
||||||
attrs: Data
|
attrs: Data
|
||||||
slots: Slots
|
slots: TypedSlots<S>
|
||||||
emit: EmitFn<E>
|
emit: EmitFn<E>
|
||||||
expose: (exposed?: Record<string, any>) => void
|
expose: (exposed?: Record<string, any>) => void
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,6 +74,7 @@ import {
|
||||||
} from './compat/compatConfig'
|
} from './compat/compatConfig'
|
||||||
import { OptionMergeFunction } from './apiCreateApp'
|
import { OptionMergeFunction } from './apiCreateApp'
|
||||||
import { LifecycleHooks } from './enums'
|
import { LifecycleHooks } from './enums'
|
||||||
|
import { SlotsType } from './componentSlots'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for declaring custom options.
|
* Interface for declaring custom options.
|
||||||
|
@ -105,6 +106,7 @@ export interface ComponentOptionsBase<
|
||||||
Extends extends ComponentOptionsMixin,
|
Extends extends ComponentOptionsMixin,
|
||||||
E extends EmitsOptions,
|
E extends EmitsOptions,
|
||||||
EE extends string = string,
|
EE extends string = string,
|
||||||
|
S extends SlotsType = {},
|
||||||
Defaults = {},
|
Defaults = {},
|
||||||
I extends ComponentInjectOptions = {},
|
I extends ComponentInjectOptions = {},
|
||||||
II extends string = string
|
II extends string = string
|
||||||
|
@ -122,7 +124,7 @@ export interface ComponentOptionsBase<
|
||||||
>
|
>
|
||||||
>
|
>
|
||||||
>,
|
>,
|
||||||
ctx: SetupContext<E>
|
ctx: SetupContext<E, S>
|
||||||
) => Promise<RawBindings> | RawBindings | RenderFunction | void
|
) => Promise<RawBindings> | RawBindings | RenderFunction | void
|
||||||
name?: string
|
name?: string
|
||||||
template?: string | object // can be a direct DOM node
|
template?: string | object // can be a direct DOM node
|
||||||
|
@ -136,6 +138,7 @@ export interface ComponentOptionsBase<
|
||||||
directives?: Record<string, Directive>
|
directives?: Record<string, Directive>
|
||||||
inheritAttrs?: boolean
|
inheritAttrs?: boolean
|
||||||
emits?: (E | EE[]) & ThisType<void>
|
emits?: (E | EE[]) & ThisType<void>
|
||||||
|
slots?: S
|
||||||
// TODO infer public instance type based on exposed keys
|
// TODO infer public instance type based on exposed keys
|
||||||
expose?: string[]
|
expose?: string[]
|
||||||
serverPrefetch?(): void | Promise<any>
|
serverPrefetch?(): void | Promise<any>
|
||||||
|
@ -216,6 +219,7 @@ export type ComponentOptionsWithoutProps<
|
||||||
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
|
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
|
||||||
E extends EmitsOptions = EmitsOptions,
|
E extends EmitsOptions = EmitsOptions,
|
||||||
EE extends string = string,
|
EE extends string = string,
|
||||||
|
S extends SlotsType = {},
|
||||||
I extends ComponentInjectOptions = {},
|
I extends ComponentInjectOptions = {},
|
||||||
II extends string = string,
|
II extends string = string,
|
||||||
PE = Props & EmitsToProps<E>
|
PE = Props & EmitsToProps<E>
|
||||||
|
@ -229,6 +233,7 @@ export type ComponentOptionsWithoutProps<
|
||||||
Extends,
|
Extends,
|
||||||
E,
|
E,
|
||||||
EE,
|
EE,
|
||||||
|
S,
|
||||||
{},
|
{},
|
||||||
I,
|
I,
|
||||||
II
|
II
|
||||||
|
@ -244,6 +249,7 @@ export type ComponentOptionsWithoutProps<
|
||||||
Mixin,
|
Mixin,
|
||||||
Extends,
|
Extends,
|
||||||
E,
|
E,
|
||||||
|
S,
|
||||||
PE,
|
PE,
|
||||||
{},
|
{},
|
||||||
false,
|
false,
|
||||||
|
@ -261,6 +267,7 @@ export type ComponentOptionsWithArrayProps<
|
||||||
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
|
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
|
||||||
E extends EmitsOptions = EmitsOptions,
|
E extends EmitsOptions = EmitsOptions,
|
||||||
EE extends string = string,
|
EE extends string = string,
|
||||||
|
S extends SlotsType = {},
|
||||||
I extends ComponentInjectOptions = {},
|
I extends ComponentInjectOptions = {},
|
||||||
II extends string = string,
|
II extends string = string,
|
||||||
Props = Prettify<Readonly<{ [key in PropNames]?: any } & EmitsToProps<E>>>
|
Props = Prettify<Readonly<{ [key in PropNames]?: any } & EmitsToProps<E>>>
|
||||||
|
@ -274,6 +281,7 @@ export type ComponentOptionsWithArrayProps<
|
||||||
Extends,
|
Extends,
|
||||||
E,
|
E,
|
||||||
EE,
|
EE,
|
||||||
|
S,
|
||||||
{},
|
{},
|
||||||
I,
|
I,
|
||||||
II
|
II
|
||||||
|
@ -289,6 +297,7 @@ export type ComponentOptionsWithArrayProps<
|
||||||
Mixin,
|
Mixin,
|
||||||
Extends,
|
Extends,
|
||||||
E,
|
E,
|
||||||
|
S,
|
||||||
Props,
|
Props,
|
||||||
{},
|
{},
|
||||||
false,
|
false,
|
||||||
|
@ -306,6 +315,7 @@ export type ComponentOptionsWithObjectProps<
|
||||||
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
|
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
|
||||||
E extends EmitsOptions = EmitsOptions,
|
E extends EmitsOptions = EmitsOptions,
|
||||||
EE extends string = string,
|
EE extends string = string,
|
||||||
|
S extends SlotsType = {},
|
||||||
I extends ComponentInjectOptions = {},
|
I extends ComponentInjectOptions = {},
|
||||||
II extends string = string,
|
II extends string = string,
|
||||||
Props = Prettify<Readonly<ExtractPropTypes<PropsOptions> & EmitsToProps<E>>>,
|
Props = Prettify<Readonly<ExtractPropTypes<PropsOptions> & EmitsToProps<E>>>,
|
||||||
|
@ -320,6 +330,7 @@ export type ComponentOptionsWithObjectProps<
|
||||||
Extends,
|
Extends,
|
||||||
E,
|
E,
|
||||||
EE,
|
EE,
|
||||||
|
S,
|
||||||
Defaults,
|
Defaults,
|
||||||
I,
|
I,
|
||||||
II
|
II
|
||||||
|
@ -335,6 +346,7 @@ export type ComponentOptionsWithObjectProps<
|
||||||
Mixin,
|
Mixin,
|
||||||
Extends,
|
Extends,
|
||||||
E,
|
E,
|
||||||
|
S,
|
||||||
Props,
|
Props,
|
||||||
Defaults,
|
Defaults,
|
||||||
false,
|
false,
|
||||||
|
@ -350,8 +362,20 @@ export type ComponentOptions<
|
||||||
M extends MethodOptions = any,
|
M extends MethodOptions = any,
|
||||||
Mixin extends ComponentOptionsMixin = any,
|
Mixin extends ComponentOptionsMixin = any,
|
||||||
Extends extends ComponentOptionsMixin = any,
|
Extends extends ComponentOptionsMixin = any,
|
||||||
E extends EmitsOptions = any
|
E extends EmitsOptions = any,
|
||||||
> = ComponentOptionsBase<Props, RawBindings, D, C, M, Mixin, Extends, E> &
|
S extends SlotsType = any
|
||||||
|
> = ComponentOptionsBase<
|
||||||
|
Props,
|
||||||
|
RawBindings,
|
||||||
|
D,
|
||||||
|
C,
|
||||||
|
M,
|
||||||
|
Mixin,
|
||||||
|
Extends,
|
||||||
|
E,
|
||||||
|
string,
|
||||||
|
S
|
||||||
|
> &
|
||||||
ThisType<
|
ThisType<
|
||||||
CreateComponentPublicInstance<
|
CreateComponentPublicInstance<
|
||||||
{},
|
{},
|
||||||
|
@ -376,6 +400,7 @@ export type ComponentOptionsMixin = ComponentOptionsBase<
|
||||||
any,
|
any,
|
||||||
any,
|
any,
|
||||||
any,
|
any,
|
||||||
|
any,
|
||||||
any
|
any
|
||||||
>
|
>
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ import {
|
||||||
ComponentInjectOptions
|
ComponentInjectOptions
|
||||||
} from './componentOptions'
|
} from './componentOptions'
|
||||||
import { EmitsOptions, EmitFn } from './componentEmits'
|
import { EmitsOptions, EmitFn } from './componentEmits'
|
||||||
import { Slots } from './componentSlots'
|
import { SlotsType, TypedSlots } from './componentSlots'
|
||||||
import { markAttrsAccessed } from './componentRenderUtils'
|
import { markAttrsAccessed } from './componentRenderUtils'
|
||||||
import { currentRenderingInstance } from './componentRenderContext'
|
import { currentRenderingInstance } from './componentRenderContext'
|
||||||
import { warn } from './warning'
|
import { warn } from './warning'
|
||||||
|
@ -89,6 +89,7 @@ type MixinToOptionTypes<T> = T extends ComponentOptionsBase<
|
||||||
infer Extends,
|
infer Extends,
|
||||||
any,
|
any,
|
||||||
any,
|
any,
|
||||||
|
any,
|
||||||
infer Defaults
|
infer Defaults
|
||||||
>
|
>
|
||||||
? OptionTypesType<P & {}, B & {}, D & {}, C & {}, M & {}, Defaults & {}> &
|
? OptionTypesType<P & {}, B & {}, D & {}, C & {}, M & {}, Defaults & {}> &
|
||||||
|
@ -141,6 +142,7 @@ export type CreateComponentPublicInstance<
|
||||||
Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
|
Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
|
||||||
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
|
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
|
||||||
E extends EmitsOptions = {},
|
E extends EmitsOptions = {},
|
||||||
|
S extends SlotsType = {},
|
||||||
PublicProps = P,
|
PublicProps = P,
|
||||||
Defaults = {},
|
Defaults = {},
|
||||||
MakeDefaultsOptional extends boolean = false,
|
MakeDefaultsOptional extends boolean = false,
|
||||||
|
@ -162,10 +164,11 @@ export type CreateComponentPublicInstance<
|
||||||
PublicC,
|
PublicC,
|
||||||
PublicM,
|
PublicM,
|
||||||
E,
|
E,
|
||||||
|
S,
|
||||||
PublicProps,
|
PublicProps,
|
||||||
PublicDefaults,
|
PublicDefaults,
|
||||||
MakeDefaultsOptional,
|
MakeDefaultsOptional,
|
||||||
ComponentOptionsBase<P, B, D, C, M, Mixin, Extends, E, string, Defaults>,
|
ComponentOptionsBase<P, B, D, C, M, Mixin, Extends, E, string, S, Defaults>,
|
||||||
I
|
I
|
||||||
>
|
>
|
||||||
|
|
||||||
|
@ -178,6 +181,7 @@ export type ComponentPublicInstance<
|
||||||
C extends ComputedOptions = {},
|
C extends ComputedOptions = {},
|
||||||
M extends MethodOptions = {},
|
M extends MethodOptions = {},
|
||||||
E extends EmitsOptions = {},
|
E extends EmitsOptions = {},
|
||||||
|
S extends SlotsType = {},
|
||||||
PublicProps = P,
|
PublicProps = P,
|
||||||
Defaults = {},
|
Defaults = {},
|
||||||
MakeDefaultsOptional extends boolean = false,
|
MakeDefaultsOptional extends boolean = false,
|
||||||
|
@ -193,7 +197,7 @@ export type ComponentPublicInstance<
|
||||||
>
|
>
|
||||||
$attrs: Data
|
$attrs: Data
|
||||||
$refs: Data
|
$refs: Data
|
||||||
$slots: Slots
|
$slots: TypedSlots<S>
|
||||||
$root: ComponentPublicInstance | null
|
$root: ComponentPublicInstance | null
|
||||||
$parent: ComponentPublicInstance | null
|
$parent: ComponentPublicInstance | null
|
||||||
$emit: EmitFn<E>
|
$emit: EmitFn<E>
|
||||||
|
|
|
@ -13,7 +13,9 @@ import {
|
||||||
ShapeFlags,
|
ShapeFlags,
|
||||||
extend,
|
extend,
|
||||||
def,
|
def,
|
||||||
SlotFlags
|
SlotFlags,
|
||||||
|
Prettify,
|
||||||
|
IfAny
|
||||||
} from '@vue/shared'
|
} from '@vue/shared'
|
||||||
import { warn } from './warning'
|
import { warn } from './warning'
|
||||||
import { isKeepAlive } from './components/KeepAlive'
|
import { isKeepAlive } from './components/KeepAlive'
|
||||||
|
@ -22,7 +24,9 @@ import { isHmrUpdating } from './hmr'
|
||||||
import { DeprecationTypes, isCompatEnabled } from './compat/compatConfig'
|
import { DeprecationTypes, isCompatEnabled } from './compat/compatConfig'
|
||||||
import { toRaw } from '@vue/reactivity'
|
import { toRaw } from '@vue/reactivity'
|
||||||
|
|
||||||
export type Slot = (...args: any[]) => VNode[]
|
export type Slot<T extends any = any> = (
|
||||||
|
...args: IfAny<T, any[], [T] | (T extends undefined ? [] : never)>
|
||||||
|
) => VNode[]
|
||||||
|
|
||||||
export type InternalSlots = {
|
export type InternalSlots = {
|
||||||
[name: string]: Slot | undefined
|
[name: string]: Slot | undefined
|
||||||
|
@ -30,6 +34,24 @@ export type InternalSlots = {
|
||||||
|
|
||||||
export type Slots = Readonly<InternalSlots>
|
export type Slots = Readonly<InternalSlots>
|
||||||
|
|
||||||
|
declare const SlotSymbol: unique symbol
|
||||||
|
export type SlotsType<T extends Record<string, any> = Record<string, any>> = {
|
||||||
|
[SlotSymbol]?: T
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TypedSlots<
|
||||||
|
S extends SlotsType,
|
||||||
|
T = NonNullable<S[typeof SlotSymbol]>
|
||||||
|
> = [keyof S] extends [never]
|
||||||
|
? Slots
|
||||||
|
: Readonly<
|
||||||
|
Prettify<{
|
||||||
|
[K in keyof T]: NonNullable<T[K]> extends (...args: any[]) => any
|
||||||
|
? T[K]
|
||||||
|
: Slot<T[K]>
|
||||||
|
}>
|
||||||
|
>
|
||||||
|
|
||||||
export type RawSlots = {
|
export type RawSlots = {
|
||||||
[name: string]: unknown
|
[name: string]: unknown
|
||||||
// manual render fn hint to skip forced children updates
|
// manual render fn hint to skip forced children updates
|
||||||
|
|
|
@ -120,8 +120,12 @@ export function h(
|
||||||
): VNode
|
): VNode
|
||||||
|
|
||||||
// functional component
|
// functional component
|
||||||
export function h<P, E extends EmitsOptions = {}>(
|
export function h<
|
||||||
type: FunctionalComponent<P, E>,
|
P,
|
||||||
|
E extends EmitsOptions = {},
|
||||||
|
S extends Record<string, any> = {}
|
||||||
|
>(
|
||||||
|
type: FunctionalComponent<P, E, S>,
|
||||||
props?: (RawProps & P) | ({} extends P ? null : never),
|
props?: (RawProps & P) | ({} extends P ? null : never),
|
||||||
children?: RawChildren | RawSlots
|
children?: RawChildren | RawSlots
|
||||||
): VNode
|
): VNode
|
||||||
|
|
|
@ -70,6 +70,7 @@ export {
|
||||||
defineEmits,
|
defineEmits,
|
||||||
defineExpose,
|
defineExpose,
|
||||||
defineOptions,
|
defineOptions,
|
||||||
|
defineSlots,
|
||||||
withDefaults,
|
withDefaults,
|
||||||
// internal
|
// internal
|
||||||
mergeDefaults,
|
mergeDefaults,
|
||||||
|
@ -243,7 +244,7 @@ export type {
|
||||||
RootRenderFunction
|
RootRenderFunction
|
||||||
} from './renderer'
|
} from './renderer'
|
||||||
export type { RootHydrateFunction } from './hydration'
|
export type { RootHydrateFunction } from './hydration'
|
||||||
export type { Slot, Slots } from './componentSlots'
|
export type { Slot, Slots, SlotsType } from './componentSlots'
|
||||||
export type {
|
export type {
|
||||||
Prop,
|
Prop,
|
||||||
PropType,
|
PropType,
|
||||||
|
|
|
@ -4,6 +4,7 @@ type _defineProps = typeof defineProps
|
||||||
type _defineEmits = typeof defineEmits
|
type _defineEmits = typeof defineEmits
|
||||||
type _defineExpose = typeof defineExpose
|
type _defineExpose = typeof defineExpose
|
||||||
type _defineOptions = typeof defineOptions
|
type _defineOptions = typeof defineOptions
|
||||||
|
type _defineSlots = typeof defineSlots
|
||||||
type _withDefaults = typeof withDefaults
|
type _withDefaults = typeof withDefaults
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
@ -11,5 +12,6 @@ declare global {
|
||||||
const defineEmits: _defineEmits
|
const defineEmits: _defineEmits
|
||||||
const defineExpose: _defineExpose
|
const defineExpose: _defineExpose
|
||||||
const defineOptions: _defineOptions
|
const defineOptions: _defineOptions
|
||||||
|
const defineSlots: _defineSlots
|
||||||
const withDefaults: _withDefaults
|
const withDefaults: _withDefaults
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,8 @@ import {
|
||||||
warn,
|
warn,
|
||||||
ConcreteComponent,
|
ConcreteComponent,
|
||||||
ComponentOptions,
|
ComponentOptions,
|
||||||
ComponentInjectOptions
|
ComponentInjectOptions,
|
||||||
|
SlotsType
|
||||||
} from '@vue/runtime-core'
|
} from '@vue/runtime-core'
|
||||||
import { camelize, extend, hyphenate, isArray, toNumber } from '@vue/shared'
|
import { camelize, extend, hyphenate, isArray, toNumber } from '@vue/shared'
|
||||||
import { hydrate, render } from '.'
|
import { hydrate, render } from '.'
|
||||||
|
@ -51,6 +52,7 @@ export function defineCustomElement<
|
||||||
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
|
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
|
||||||
E extends EmitsOptions = EmitsOptions,
|
E extends EmitsOptions = EmitsOptions,
|
||||||
EE extends string = string,
|
EE extends string = string,
|
||||||
|
S extends SlotsType = {},
|
||||||
I extends ComponentInjectOptions = {},
|
I extends ComponentInjectOptions = {},
|
||||||
II extends string = string
|
II extends string = string
|
||||||
>(
|
>(
|
||||||
|
@ -64,6 +66,7 @@ export function defineCustomElement<
|
||||||
Extends,
|
Extends,
|
||||||
E,
|
E,
|
||||||
EE,
|
EE,
|
||||||
|
S,
|
||||||
I,
|
I,
|
||||||
II
|
II
|
||||||
> & { styles?: string[] }
|
> & { styles?: string[] }
|
||||||
|
@ -80,6 +83,7 @@ export function defineCustomElement<
|
||||||
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
|
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
|
||||||
E extends EmitsOptions = Record<string, any>,
|
E extends EmitsOptions = Record<string, any>,
|
||||||
EE extends string = string,
|
EE extends string = string,
|
||||||
|
S extends SlotsType = {},
|
||||||
I extends ComponentInjectOptions = {},
|
I extends ComponentInjectOptions = {},
|
||||||
II extends string = string
|
II extends string = string
|
||||||
>(
|
>(
|
||||||
|
@ -93,6 +97,7 @@ export function defineCustomElement<
|
||||||
Extends,
|
Extends,
|
||||||
E,
|
E,
|
||||||
EE,
|
EE,
|
||||||
|
S,
|
||||||
I,
|
I,
|
||||||
II
|
II
|
||||||
> & { styles?: string[] }
|
> & { styles?: string[] }
|
||||||
|
@ -109,6 +114,7 @@ export function defineCustomElement<
|
||||||
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
|
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
|
||||||
E extends EmitsOptions = Record<string, any>,
|
E extends EmitsOptions = Record<string, any>,
|
||||||
EE extends string = string,
|
EE extends string = string,
|
||||||
|
S extends SlotsType = {},
|
||||||
I extends ComponentInjectOptions = {},
|
I extends ComponentInjectOptions = {},
|
||||||
II extends string = string
|
II extends string = string
|
||||||
>(
|
>(
|
||||||
|
@ -122,6 +128,7 @@ export function defineCustomElement<
|
||||||
Extends,
|
Extends,
|
||||||
E,
|
E,
|
||||||
EE,
|
EE,
|
||||||
|
S,
|
||||||
I,
|
I,
|
||||||
II
|
II
|
||||||
> & { styles?: string[] }
|
> & { styles?: string[] }
|
||||||
|
|
Loading…
Reference in New Issue