fix(types): preserve and expose original options on defineComponent return type (#5416)
fix #3796
This commit is contained in:
parent
32e53bfd47
commit
98b821d94a
@ -111,7 +111,7 @@ export function defineAsyncComponent<
|
||||
)
|
||||
}
|
||||
|
||||
return defineComponent({
|
||||
return defineComponent<{}>({
|
||||
name: 'AsyncComponentWrapper',
|
||||
|
||||
__asyncLoader: load,
|
||||
|
@ -6,7 +6,8 @@ import {
|
||||
ComponentOptionsWithObjectProps,
|
||||
ComponentOptionsMixin,
|
||||
RenderFunction,
|
||||
ComponentOptionsBase
|
||||
ComponentOptionsBase,
|
||||
ComponentProvideOptions
|
||||
} from './componentOptions'
|
||||
import {
|
||||
SetupContext,
|
||||
@ -40,6 +41,8 @@ export type DefineComponent<
|
||||
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
|
||||
E extends EmitsOptions = {},
|
||||
EE extends string = string,
|
||||
Provide extends ComponentProvideOptions = ComponentProvideOptions,
|
||||
RawOptions extends {} = {},
|
||||
PP = PublicProps,
|
||||
Props = Readonly<
|
||||
PropsOrPropOptions extends ComponentPropsOptions
|
||||
@ -48,22 +51,23 @@ export type DefineComponent<
|
||||
> &
|
||||
({} extends E ? {} : EmitsToProps<E>),
|
||||
Defaults = ExtractDefaultPropTypes<PropsOrPropOptions>
|
||||
> = ComponentPublicInstanceConstructor<
|
||||
CreateComponentPublicInstance<
|
||||
Props,
|
||||
RawBindings,
|
||||
D,
|
||||
C,
|
||||
M,
|
||||
Mixin,
|
||||
Extends,
|
||||
E,
|
||||
PP & Props,
|
||||
Defaults,
|
||||
true
|
||||
> = RawOptions &
|
||||
ComponentPublicInstanceConstructor<
|
||||
CreateComponentPublicInstance<
|
||||
Props,
|
||||
RawBindings,
|
||||
D,
|
||||
C,
|
||||
M,
|
||||
Mixin,
|
||||
Extends,
|
||||
E,
|
||||
PP & Props,
|
||||
Defaults,
|
||||
true
|
||||
> &
|
||||
Props
|
||||
> &
|
||||
Props
|
||||
> &
|
||||
ComponentOptionsBase<
|
||||
Props,
|
||||
RawBindings,
|
||||
@ -74,7 +78,8 @@ export type DefineComponent<
|
||||
Extends,
|
||||
E,
|
||||
EE,
|
||||
Defaults
|
||||
Defaults,
|
||||
Provide
|
||||
> &
|
||||
PP
|
||||
|
||||
@ -104,20 +109,36 @@ export function defineComponent<
|
||||
Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
|
||||
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
|
||||
E extends EmitsOptions = EmitsOptions,
|
||||
EE extends string = string
|
||||
EE extends string = string,
|
||||
Provide extends ComponentProvideOptions = ComponentProvideOptions,
|
||||
Options extends {} = {}
|
||||
>(
|
||||
options: ComponentOptionsWithoutProps<
|
||||
Props,
|
||||
RawBindings,
|
||||
D,
|
||||
C,
|
||||
M,
|
||||
Mixin,
|
||||
Extends,
|
||||
E,
|
||||
EE
|
||||
>
|
||||
): DefineComponent<Props, RawBindings, D, C, M, Mixin, Extends, E, EE>
|
||||
options: Options &
|
||||
ComponentOptionsWithoutProps<
|
||||
Props,
|
||||
RawBindings,
|
||||
D,
|
||||
C,
|
||||
M,
|
||||
Mixin,
|
||||
Extends,
|
||||
E,
|
||||
EE,
|
||||
Provide
|
||||
>
|
||||
): DefineComponent<
|
||||
Props,
|
||||
RawBindings,
|
||||
D,
|
||||
C,
|
||||
M,
|
||||
Mixin,
|
||||
Extends,
|
||||
E,
|
||||
EE,
|
||||
Provide,
|
||||
Options
|
||||
>
|
||||
|
||||
// overload 3: object format with array props declaration
|
||||
// props inferred as { [key in PropNames]?: any }
|
||||
@ -131,19 +152,23 @@ export function defineComponent<
|
||||
Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
|
||||
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
|
||||
E extends EmitsOptions = Record<string, any>,
|
||||
EE extends string = string
|
||||
EE extends string = string,
|
||||
Provide extends ComponentProvideOptions = ComponentProvideOptions,
|
||||
Options extends {} = {}
|
||||
>(
|
||||
options: ComponentOptionsWithArrayProps<
|
||||
PropNames,
|
||||
RawBindings,
|
||||
D,
|
||||
C,
|
||||
M,
|
||||
Mixin,
|
||||
Extends,
|
||||
E,
|
||||
EE
|
||||
>
|
||||
options: Options &
|
||||
ComponentOptionsWithArrayProps<
|
||||
PropNames,
|
||||
RawBindings,
|
||||
D,
|
||||
C,
|
||||
M,
|
||||
Mixin,
|
||||
Extends,
|
||||
E,
|
||||
EE,
|
||||
Provide
|
||||
>
|
||||
): DefineComponent<
|
||||
Readonly<{ [key in PropNames]?: any }>,
|
||||
RawBindings,
|
||||
@ -153,7 +178,9 @@ export function defineComponent<
|
||||
Mixin,
|
||||
Extends,
|
||||
E,
|
||||
EE
|
||||
EE,
|
||||
Provide,
|
||||
Options
|
||||
>
|
||||
|
||||
// overload 4: object format with object props declaration
|
||||
@ -169,20 +196,36 @@ export function defineComponent<
|
||||
Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
|
||||
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
|
||||
E extends EmitsOptions = Record<string, any>,
|
||||
EE extends string = string
|
||||
EE extends string = string,
|
||||
Provide extends ComponentProvideOptions = ComponentProvideOptions,
|
||||
Options extends {} = {}
|
||||
>(
|
||||
options: ComponentOptionsWithObjectProps<
|
||||
PropsOptions,
|
||||
RawBindings,
|
||||
D,
|
||||
C,
|
||||
M,
|
||||
Mixin,
|
||||
Extends,
|
||||
E,
|
||||
EE
|
||||
>
|
||||
): DefineComponent<PropsOptions, RawBindings, D, C, M, Mixin, Extends, E, EE>
|
||||
options: Options &
|
||||
ComponentOptionsWithObjectProps<
|
||||
PropsOptions,
|
||||
RawBindings,
|
||||
D,
|
||||
C,
|
||||
M,
|
||||
Mixin,
|
||||
Extends,
|
||||
E,
|
||||
EE,
|
||||
Provide
|
||||
>
|
||||
): DefineComponent<
|
||||
PropsOptions,
|
||||
RawBindings,
|
||||
D,
|
||||
C,
|
||||
M,
|
||||
Mixin,
|
||||
Extends,
|
||||
E,
|
||||
EE,
|
||||
Provide,
|
||||
Options
|
||||
>
|
||||
|
||||
// implementation, close to no-op
|
||||
export function defineComponent(options: unknown) {
|
||||
|
@ -117,8 +117,9 @@ export interface ComponentOptionsBase<
|
||||
Extends extends ComponentOptionsMixin,
|
||||
E extends EmitsOptions,
|
||||
EE extends string = string,
|
||||
Defaults = {}
|
||||
> extends LegacyOptions<Props, D, C, M, Mixin, Extends>,
|
||||
Defaults = {},
|
||||
Provide extends ComponentProvideOptions = ComponentProvideOptions
|
||||
> extends LegacyOptions<Props, D, C, M, Mixin, Extends, Provide>,
|
||||
ComponentInternalOptions,
|
||||
ComponentCustomOptions {
|
||||
setup?: (
|
||||
@ -224,6 +225,7 @@ export type ComponentOptionsWithoutProps<
|
||||
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
|
||||
E extends EmitsOptions = EmitsOptions,
|
||||
EE extends string = string,
|
||||
Provide extends ComponentProvideOptions = ComponentProvideOptions,
|
||||
PE = Props & EmitsToProps<E>
|
||||
> = ComponentOptionsBase<
|
||||
PE,
|
||||
@ -235,7 +237,8 @@ export type ComponentOptionsWithoutProps<
|
||||
Extends,
|
||||
E,
|
||||
EE,
|
||||
{}
|
||||
{},
|
||||
Provide
|
||||
> & {
|
||||
props?: undefined
|
||||
} & ThisType<
|
||||
@ -252,6 +255,7 @@ export type ComponentOptionsWithArrayProps<
|
||||
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
|
||||
E extends EmitsOptions = EmitsOptions,
|
||||
EE extends string = string,
|
||||
Provide extends ComponentProvideOptions = ComponentProvideOptions,
|
||||
Props = Readonly<{ [key in PropNames]?: any }> & EmitsToProps<E>
|
||||
> = ComponentOptionsBase<
|
||||
Props,
|
||||
@ -263,7 +267,8 @@ export type ComponentOptionsWithArrayProps<
|
||||
Extends,
|
||||
E,
|
||||
EE,
|
||||
{}
|
||||
{},
|
||||
Provide
|
||||
> & {
|
||||
props: PropNames[]
|
||||
} & ThisType<
|
||||
@ -289,6 +294,7 @@ export type ComponentOptionsWithObjectProps<
|
||||
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
|
||||
E extends EmitsOptions = EmitsOptions,
|
||||
EE extends string = string,
|
||||
Provide extends ComponentProvideOptions = ComponentProvideOptions,
|
||||
Props = Readonly<ExtractPropTypes<PropsOptions>> & EmitsToProps<E>,
|
||||
Defaults = ExtractDefaultPropTypes<PropsOptions>
|
||||
> = ComponentOptionsBase<
|
||||
@ -301,7 +307,8 @@ export type ComponentOptionsWithObjectProps<
|
||||
Extends,
|
||||
E,
|
||||
EE,
|
||||
Defaults
|
||||
Defaults,
|
||||
Provide
|
||||
> & {
|
||||
props: PropsOptions & ThisType<void>
|
||||
} & ThisType<
|
||||
@ -384,6 +391,10 @@ type ComponentWatchOptionItem = WatchOptionItem | WatchOptionItem[]
|
||||
|
||||
type ComponentWatchOptions = Record<string, ComponentWatchOptionItem>
|
||||
|
||||
export type ComponentProvideOptions = ObjectProvideOptions | Function
|
||||
|
||||
type ObjectProvideOptions = Record<string | symbol, unknown>
|
||||
|
||||
type ComponentInjectOptions = string[] | ObjectInjectOptions
|
||||
|
||||
type ObjectInjectOptions = Record<
|
||||
@ -397,7 +408,8 @@ interface LegacyOptions<
|
||||
C extends ComputedOptions,
|
||||
M extends MethodOptions,
|
||||
Mixin extends ComponentOptionsMixin,
|
||||
Extends extends ComponentOptionsMixin
|
||||
Extends extends ComponentOptionsMixin,
|
||||
Provide extends ComponentProvideOptions = ComponentProvideOptions
|
||||
> {
|
||||
compatConfig?: CompatConfig
|
||||
|
||||
@ -431,7 +443,7 @@ interface LegacyOptions<
|
||||
computed?: C
|
||||
methods?: M
|
||||
watch?: ComponentWatchOptions
|
||||
provide?: Data | Function
|
||||
provide?: Provide
|
||||
inject?: ComponentInjectOptions
|
||||
|
||||
// assets
|
||||
|
@ -34,7 +34,8 @@ import {
|
||||
OptionTypesKeys,
|
||||
resolveMergedOptions,
|
||||
shouldCacheAccess,
|
||||
MergedComponentOptionsOverride
|
||||
MergedComponentOptionsOverride,
|
||||
ComponentProvideOptions
|
||||
} from './componentOptions'
|
||||
import { EmitsOptions, EmitFn } from './componentEmits'
|
||||
import { Slots } from './componentSlots'
|
||||
@ -150,7 +151,8 @@ export type CreateComponentPublicInstance<
|
||||
PublicM extends MethodOptions = UnwrapMixinsType<PublicMixin, 'M'> &
|
||||
EnsureNonVoid<M>,
|
||||
PublicDefaults = UnwrapMixinsType<PublicMixin, 'Defaults'> &
|
||||
EnsureNonVoid<Defaults>
|
||||
EnsureNonVoid<Defaults>,
|
||||
Provide extends ComponentProvideOptions = ComponentProvideOptions
|
||||
> = ComponentPublicInstance<
|
||||
PublicP,
|
||||
PublicB,
|
||||
@ -161,7 +163,19 @@ export type CreateComponentPublicInstance<
|
||||
PublicProps,
|
||||
PublicDefaults,
|
||||
MakeDefaultsOptional,
|
||||
ComponentOptionsBase<P, B, D, C, M, Mixin, Extends, E, string, Defaults>
|
||||
ComponentOptionsBase<
|
||||
P,
|
||||
B,
|
||||
D,
|
||||
C,
|
||||
M,
|
||||
Mixin,
|
||||
Extends,
|
||||
E,
|
||||
string,
|
||||
Defaults,
|
||||
Provide
|
||||
>
|
||||
>
|
||||
|
||||
// public properties exposed on the proxy, which is used as the render context
|
||||
|
@ -49,96 +49,98 @@ describe('with object props', () => {
|
||||
|
||||
type GT = string & { __brand: unknown }
|
||||
|
||||
const MyComponent = defineComponent({
|
||||
props: {
|
||||
a: Number,
|
||||
// required should make property non-void
|
||||
b: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
e: Function,
|
||||
h: Boolean,
|
||||
j: Function as PropType<undefined | (() => string | undefined)>,
|
||||
// default value should infer type and make it non-void
|
||||
bb: {
|
||||
default: 'hello'
|
||||
},
|
||||
bbb: {
|
||||
// Note: default function value requires arrow syntax + explicit
|
||||
// annotation
|
||||
default: (props: any) => (props.bb as string) || 'foo'
|
||||
},
|
||||
bbbb: {
|
||||
type: String,
|
||||
default: undefined
|
||||
},
|
||||
bbbbb: {
|
||||
type: String,
|
||||
default: () => undefined
|
||||
},
|
||||
// explicit type casting
|
||||
cc: Array as PropType<string[]>,
|
||||
// required + type casting
|
||||
dd: {
|
||||
type: Object as PropType<{ n: 1 }>,
|
||||
required: true
|
||||
},
|
||||
// return type
|
||||
ee: Function as PropType<() => string>,
|
||||
// arguments + object return
|
||||
ff: Function as PropType<(a: number, b: string) => { a: boolean }>,
|
||||
// explicit type casting with constructor
|
||||
ccc: Array as () => string[],
|
||||
// required + constructor type casting
|
||||
ddd: {
|
||||
type: Array as () => string[],
|
||||
required: true
|
||||
},
|
||||
// required + object return
|
||||
eee: {
|
||||
type: Function as PropType<() => { a: string }>,
|
||||
required: true
|
||||
},
|
||||
// required + arguments + object return
|
||||
fff: {
|
||||
type: Function as PropType<(a: number, b: string) => { a: boolean }>,
|
||||
required: true
|
||||
},
|
||||
hhh: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
// default + type casting
|
||||
ggg: {
|
||||
type: String as PropType<'foo' | 'bar'>,
|
||||
default: 'foo'
|
||||
},
|
||||
// default + function
|
||||
ffff: {
|
||||
type: Function as PropType<(a: number, b: string) => { a: boolean }>,
|
||||
default: (a: number, b: string) => ({ a: a > +b })
|
||||
},
|
||||
// union + function with different return types
|
||||
iii: Function as PropType<(() => string) | (() => number)>,
|
||||
// union + function with different args & same return type
|
||||
jjj: {
|
||||
type: Function as PropType<
|
||||
((arg1: string) => string) | ((arg1: string, arg2: string) => string)
|
||||
>,
|
||||
required: true
|
||||
},
|
||||
kkk: null,
|
||||
validated: {
|
||||
type: String,
|
||||
// validator requires explicit annotation
|
||||
validator: (val: unknown) => val !== ''
|
||||
},
|
||||
date: Date,
|
||||
l: [Date],
|
||||
ll: [Date, Number],
|
||||
lll: [String, Number]
|
||||
const props = {
|
||||
a: Number,
|
||||
// required should make property non-void
|
||||
b: {
|
||||
type: String,
|
||||
required: true as true
|
||||
},
|
||||
e: Function,
|
||||
h: Boolean,
|
||||
j: Function as PropType<undefined | (() => string | undefined)>,
|
||||
// default value should infer type and make it non-void
|
||||
bb: {
|
||||
default: 'hello'
|
||||
},
|
||||
bbb: {
|
||||
// Note: default function value requires arrow syntax + explicit
|
||||
// annotation
|
||||
default: (props: any) => (props.bb as string) || 'foo'
|
||||
},
|
||||
bbbb: {
|
||||
type: String,
|
||||
default: undefined
|
||||
},
|
||||
bbbbb: {
|
||||
type: String,
|
||||
default: () => undefined
|
||||
},
|
||||
// explicit type casting
|
||||
cc: Array as PropType<string[]>,
|
||||
// required + type casting
|
||||
dd: {
|
||||
type: Object as PropType<{ n: 1 }>,
|
||||
required: true as true
|
||||
},
|
||||
// return type
|
||||
ee: Function as PropType<() => string>,
|
||||
// arguments + object return
|
||||
ff: Function as PropType<(a: number, b: string) => { a: boolean }>,
|
||||
// explicit type casting with constructor
|
||||
ccc: Array as () => string[],
|
||||
// required + constructor type casting
|
||||
ddd: {
|
||||
type: Array as () => string[],
|
||||
required: true as true
|
||||
},
|
||||
// required + object return
|
||||
eee: {
|
||||
type: Function as PropType<() => { a: string }>,
|
||||
required: true as true
|
||||
},
|
||||
// required + arguments + object return
|
||||
fff: {
|
||||
type: Function as PropType<(a: number, b: string) => { a: boolean }>,
|
||||
required: true as true
|
||||
},
|
||||
hhh: {
|
||||
type: Boolean,
|
||||
required: true as true
|
||||
},
|
||||
// default + type casting
|
||||
ggg: {
|
||||
type: String as PropType<'foo' | 'bar'>,
|
||||
default: 'foo'
|
||||
},
|
||||
// default + function
|
||||
ffff: {
|
||||
type: Function as PropType<(a: number, b: string) => { a: boolean }>,
|
||||
default: (a: number, b: string) => ({ a: a > +b })
|
||||
},
|
||||
// union + function with different return types
|
||||
iii: Function as PropType<(() => string) | (() => number)>,
|
||||
// union + function with different args & same return type
|
||||
jjj: {
|
||||
type: Function as PropType<
|
||||
((arg1: string) => string) | ((arg1: string, arg2: string) => string)
|
||||
>,
|
||||
required: true as true
|
||||
},
|
||||
kkk: null,
|
||||
validated: {
|
||||
type: String,
|
||||
// validator requires explicit annotation
|
||||
validator: (val: unknown) => val !== ''
|
||||
},
|
||||
date: Date,
|
||||
l: [Date],
|
||||
ll: [Date, Number],
|
||||
lll: [String, Number]
|
||||
}
|
||||
|
||||
const MyComponent = defineComponent({
|
||||
props,
|
||||
setup(props) {
|
||||
// type assertion. See https://github.com/SamVerschueren/tsd
|
||||
expectType<ExpectedProps['a']>(props.a)
|
||||
@ -188,6 +190,9 @@ describe('with object props', () => {
|
||||
})
|
||||
}
|
||||
},
|
||||
provide() {
|
||||
return {}
|
||||
},
|
||||
render() {
|
||||
const props = this.$props
|
||||
expectType<ExpectedProps['a']>(props.a)
|
||||
@ -258,6 +263,18 @@ describe('with object props', () => {
|
||||
|
||||
expectType<Component>(MyComponent)
|
||||
|
||||
expectType<typeof props>(MyComponent.props)
|
||||
// @ts-expect-error it should be an object and not any
|
||||
expectError<[]>(MyComponent.props)
|
||||
|
||||
expectType<() => {}>(MyComponent.provide)
|
||||
// @ts-expect-error
|
||||
expectError<[]>(MyComponent.provide)
|
||||
|
||||
expectType<() => null>(MyComponent.render)
|
||||
|
||||
expectType<Function | undefined>(defineComponent({}).render)
|
||||
|
||||
// Test TSX
|
||||
expectType<JSX.Element>(
|
||||
<MyComponent
|
||||
|
Loading…
Reference in New Issue
Block a user