types: improve h() and TSX type inference
- Should allow extraneous props as attrs in TSX - Should check props when using constructor type returned by createComponent() in h()
This commit is contained in:
parent
b114cdf6ee
commit
3a6dcd3aba
@ -67,7 +67,14 @@ test('createComponent type inference', () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
// test TSX props inference
|
// test TSX props inference
|
||||||
;<MyComponent a={1} b="foo" dd={['foo']} ddd={['foo']} />
|
;<MyComponent
|
||||||
|
a={1}
|
||||||
|
b="foo"
|
||||||
|
dd={['foo']}
|
||||||
|
ddd={['foo']}
|
||||||
|
// should allow extraneous as attrs
|
||||||
|
class="bar"
|
||||||
|
/>
|
||||||
})
|
})
|
||||||
|
|
||||||
test('type inference w/ optional props declaration', () => {
|
test('type inference w/ optional props declaration', () => {
|
||||||
|
@ -9,13 +9,31 @@ import { SetupContext, RenderFunction } from './component'
|
|||||||
import { ComponentPublicInstance } from './componentProxy'
|
import { ComponentPublicInstance } from './componentProxy'
|
||||||
import { ExtractPropTypes } from './componentProps'
|
import { ExtractPropTypes } from './componentProps'
|
||||||
import { isFunction } from '@vue/shared'
|
import { isFunction } from '@vue/shared'
|
||||||
|
import { Ref } from '@vue/reactivity'
|
||||||
|
|
||||||
|
interface BaseProps {
|
||||||
|
[key: string]: any
|
||||||
|
key?: string | number
|
||||||
|
ref?: string | Ref | Function
|
||||||
|
}
|
||||||
|
|
||||||
// overload 1: direct setup function
|
// overload 1: direct setup function
|
||||||
// (uses user defined props interface)
|
// (uses user defined props interface)
|
||||||
|
// __isConstructor: true is a type-only differentiator to avoid returned
|
||||||
|
// constructor type from being matched as an options object in h()
|
||||||
export function createComponent<Props, RawBindings = object>(
|
export function createComponent<Props, RawBindings = object>(
|
||||||
setup: (props: Props, ctx: SetupContext) => RawBindings | RenderFunction
|
setup: (props: Props, ctx: SetupContext) => RawBindings | RenderFunction
|
||||||
): {
|
): {
|
||||||
new (): ComponentPublicInstance<Props, RawBindings>
|
__isConstructor: true
|
||||||
|
new (): ComponentPublicInstance<
|
||||||
|
Props,
|
||||||
|
RawBindings,
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
// public props
|
||||||
|
BaseProps & Props
|
||||||
|
>
|
||||||
}
|
}
|
||||||
|
|
||||||
// overload 2: object format with no props
|
// overload 2: object format with no props
|
||||||
@ -30,11 +48,19 @@ export function createComponent<
|
|||||||
>(
|
>(
|
||||||
options: ComponentOptionsWithoutProps<Props, RawBindings, D, C, M>
|
options: ComponentOptionsWithoutProps<Props, RawBindings, D, C, M>
|
||||||
): {
|
): {
|
||||||
new (): ComponentPublicInstance<Props, RawBindings, D, C, M>
|
__isConstructor: true
|
||||||
|
new (): ComponentPublicInstance<
|
||||||
|
Props,
|
||||||
|
RawBindings,
|
||||||
|
D,
|
||||||
|
C,
|
||||||
|
M,
|
||||||
|
BaseProps & Props
|
||||||
|
>
|
||||||
}
|
}
|
||||||
|
|
||||||
// overload 3: object format with array props declaration
|
// overload 3: object format with array props declaration
|
||||||
// props inferred as { [key in PropNames]?: unknown }
|
// props inferred as { [key in PropNames]?: any }
|
||||||
// return type is for Vetur and TSX support
|
// return type is for Vetur and TSX support
|
||||||
export function createComponent<
|
export function createComponent<
|
||||||
PropNames extends string,
|
PropNames extends string,
|
||||||
@ -45,13 +71,9 @@ export function createComponent<
|
|||||||
>(
|
>(
|
||||||
options: ComponentOptionsWithArrayProps<PropNames, RawBindings, D, C, M>
|
options: ComponentOptionsWithArrayProps<PropNames, RawBindings, D, C, M>
|
||||||
): {
|
): {
|
||||||
new (): ComponentPublicInstance<
|
__isConstructor: true
|
||||||
{ [key in PropNames]?: unknown },
|
// array props technically doesn't place any contraints on props in TSX
|
||||||
RawBindings,
|
new (): ComponentPublicInstance<BaseProps, RawBindings, D, C, M>
|
||||||
D,
|
|
||||||
C,
|
|
||||||
M
|
|
||||||
>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// overload 4: object format with object props declaration
|
// overload 4: object format with object props declaration
|
||||||
@ -65,14 +87,15 @@ export function createComponent<
|
|||||||
>(
|
>(
|
||||||
options: ComponentOptionsWithObjectProps<PropsOptions, RawBindings, D, C, M>
|
options: ComponentOptionsWithObjectProps<PropsOptions, RawBindings, D, C, M>
|
||||||
): {
|
): {
|
||||||
|
__isConstructor: true
|
||||||
// for Vetur and TSX support
|
// for Vetur and TSX support
|
||||||
new (): ComponentPublicInstance<
|
new (): ComponentPublicInstance<
|
||||||
ExtractPropTypes<PropsOptions>,
|
ExtractPropTypes<PropsOptions, false>,
|
||||||
RawBindings,
|
RawBindings,
|
||||||
D,
|
D,
|
||||||
C,
|
C,
|
||||||
M,
|
M,
|
||||||
ExtractPropTypes<PropsOptions, false>
|
BaseProps & ExtractPropTypes<PropsOptions, false>
|
||||||
>
|
>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,6 +65,10 @@ export interface ComponentOptionsBase<
|
|||||||
components?: Record<string, Component>
|
components?: Record<string, Component>
|
||||||
directives?: Record<string, Directive>
|
directives?: Record<string, Directive>
|
||||||
inheritAttrs?: boolean
|
inheritAttrs?: boolean
|
||||||
|
|
||||||
|
// type-only differentiator to separate OptionWihtoutProps from a constructor
|
||||||
|
// type returned by createComponent()
|
||||||
|
__isConstructor?: never
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ComponentOptionsWithoutProps<
|
export type ComponentOptionsWithoutProps<
|
||||||
|
@ -133,9 +133,7 @@ export function h<P>(
|
|||||||
): VNode
|
): VNode
|
||||||
export function h<P extends string>(
|
export function h<P extends string>(
|
||||||
type: ComponentOptionsWithArrayProps<P>,
|
type: ComponentOptionsWithArrayProps<P>,
|
||||||
// TODO for now this doesn't really do anything, but it would become useful
|
props?: RawProps | null,
|
||||||
// if we make props required by default
|
|
||||||
props?: (RawProps & { [key in P]?: any }) | null,
|
|
||||||
children?: RawChildren | RawSlots
|
children?: RawChildren | RawSlots
|
||||||
): VNode
|
): VNode
|
||||||
export function h<P>(
|
export function h<P>(
|
||||||
|
Loading…
Reference in New Issue
Block a user