AllowedComponentProps,
ComponentCustomProps
} from './component'
-import { ExtractPropTypes, ComponentPropsOptions } from './componentProps'
+import {
+ ExtractPropTypes,
+ ComponentPropsOptions,
+ ExtractDefaultPropTypes
+} from './componentProps'
import { EmitsOptions } from './componentEmits'
import { isFunction } from '@vue/shared'
import { VNodeProps } from './vnode'
E extends EmitsOptions = Record<string, any>,
EE extends string = string,
PP = PublicProps,
- RequiredProps = Readonly<ExtractPropTypes<PropsOrPropOptions>>,
- OptionalProps = Readonly<ExtractPropTypes<PropsOrPropOptions, false>>
+ Props = Readonly<ExtractPropTypes<PropsOrPropOptions>>,
+ Defaults = ExtractDefaultPropTypes<PropsOrPropOptions>
> = ComponentPublicInstanceConstructor<
CreateComponentPublicInstance<
- OptionalProps,
+ Props,
RawBindings,
D,
C,
Mixin,
Extends,
E,
- PP & OptionalProps
+ PP & Props,
+ Defaults,
+ true
> &
- RequiredProps
+ Props
> &
ComponentOptionsBase<
- RequiredProps,
+ Props,
RawBindings,
D,
C,
Mixin,
Extends,
E,
- EE
+ EE,
+ Defaults
> &
PP
WritableComputedOptions,
toRaw
} from '@vue/reactivity'
-import { ComponentObjectPropsOptions, ExtractPropTypes } from './componentProps'
+import {
+ ComponentObjectPropsOptions,
+ ExtractPropTypes,
+ ExtractDefaultPropTypes
+} from './componentProps'
import { EmitsOptions } from './componentEmits'
import { Directive } from './directives'
import {
Mixin extends ComponentOptionsMixin,
Extends extends ComponentOptionsMixin,
E extends EmitsOptions,
- EE extends string = string
+ EE extends string = string,
+ Defaults = {}
>
extends LegacyOptions<Props, D, C, M, Mixin, Extends>,
ComponentInternalOptions,
__isFragment?: never
__isTeleport?: never
__isSuspense?: never
+
+ __defaults?: Defaults
}
export type ComponentOptionsWithoutProps<
Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
E extends EmitsOptions = EmitsOptions,
- EE extends string = string
-> = ComponentOptionsBase<Props, RawBindings, D, C, M, Mixin, Extends, E, EE> & {
+ EE extends string = string,
+ Defaults = {}
+> = ComponentOptionsBase<
+ Props,
+ RawBindings,
+ D,
+ C,
+ M,
+ Mixin,
+ Extends,
+ E,
+ EE,
+ Defaults
+> & {
props?: undefined
} & ThisType<
CreateComponentPublicInstance<
Mixin,
Extends,
E,
- Readonly<Props>
+ Readonly<Props>,
+ Defaults,
+ false
>
>
E extends EmitsOptions = EmitsOptions,
EE extends string = string,
Props = Readonly<{ [key in PropNames]?: any }>
-> = ComponentOptionsBase<Props, RawBindings, D, C, M, Mixin, Extends, E, EE> & {
+> = ComponentOptionsBase<
+ Props,
+ RawBindings,
+ D,
+ C,
+ M,
+ Mixin,
+ Extends,
+ E,
+ EE,
+ {}
+> & {
props: PropNames[]
} & ThisType<
CreateComponentPublicInstance<
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
E extends EmitsOptions = EmitsOptions,
EE extends string = string,
- Props = Readonly<ExtractPropTypes<PropsOptions>>
-> = ComponentOptionsBase<Props, RawBindings, D, C, M, Mixin, Extends, E, EE> & {
+ Props = Readonly<ExtractPropTypes<PropsOptions>>,
+ Defaults = ExtractDefaultPropTypes<PropsOptions>
+> = ComponentOptionsBase<
+ Props,
+ RawBindings,
+ D,
+ C,
+ M,
+ Mixin,
+ Extends,
+ E,
+ EE,
+ Defaults
+> & {
props: PropsOptions & ThisType<void>
} & ThisType<
CreateComponentPublicInstance<
M,
Mixin,
Extends,
- E
+ E,
+ Props,
+ Defaults,
+ false
>
>
any,
any,
any,
+ any,
any
>
delimiters?: [string, string]
}
-export type OptionTypesKeys = 'P' | 'B' | 'D' | 'C' | 'M'
+export type OptionTypesKeys = 'P' | 'B' | 'D' | 'C' | 'M' | 'Defaults'
export type OptionTypesType<
P = {},
B = {},
D = {},
C extends ComputedOptions = {},
- M extends MethodOptions = {}
+ M extends MethodOptions = {},
+ Defaults = {}
> = {
P: P
B: B
D: D
C: C
M: M
+ Defaults: Defaults
}
const enum OptionTypes {
? { new (): TConstructor; (): T; readonly prototype: TConstructor } // Create Function like constructor
: never
-type RequiredKeys<T, MakeDefaultRequired> = {
- [K in keyof T]: T[K] extends
- | { required: true }
- | (MakeDefaultRequired extends true ? { default: any } : never)
- ? K
- : never
+type RequiredKeys<T> = {
+ [K in keyof T]: T[K] extends { required: true } | { default: any } ? K : never
}[keyof T]
-type OptionalKeys<T, MakeDefaultRequired> = Exclude<
- keyof T,
- RequiredKeys<T, MakeDefaultRequired>
->
+type OptionalKeys<T> = Exclude<keyof T, RequiredKeys<T>>
+
+type DefaultKeys<T> = {
+ [K in keyof T]: T[K] extends { default: any } ? K : never
+}[keyof T]
type InferPropType<T> = T extends null
? any // null & true would fail to infer
? boolean
: T extends Prop<infer V, infer D> ? (unknown extends V ? D : V) : T
-export type ExtractPropTypes<
- O,
- MakeDefaultRequired extends boolean = true
-> = O extends object
- ? { [K in RequiredKeys<O, MakeDefaultRequired>]: InferPropType<O[K]> } &
- { [K in OptionalKeys<O, MakeDefaultRequired>]?: InferPropType<O[K]> }
+export type ExtractPropTypes<O> = O extends object
+ ? { [K in RequiredKeys<O>]: InferPropType<O[K]> } &
+ { [K in OptionalKeys<O>]?: InferPropType<O[K]> }
: { [K in string]: any }
const enum BooleanFlags {
shouldCastTrue
}
+// extract props which defined with default from prop options
+export type ExtractDefaultPropTypes<O> = O extends object
+ ? { [K in DefaultKeys<O>]: InferPropType<O[K]> }
+ : {}
+
type NormalizedProp =
| null
| (PropOptions & {
infer M,
infer Mixin,
infer Extends,
- any
+ any,
+ any,
+ infer Defaults
>
- ? OptionTypesType<P & {}, B & {}, D & {}, C & {}, M & {}> &
+ ? OptionTypesType<P & {}, B & {}, D & {}, C & {}, M & {}, Defaults & {}> &
IntersectionMixin<Mixin> &
IntersectionMixin<Extends>
: never
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
E extends EmitsOptions = {},
PublicProps = P,
+ Defaults = {},
+ MakeDefaultsOptional extends boolean = false,
PublicMixin = IntersectionMixin<Mixin> & IntersectionMixin<Extends>,
PublicP = UnwrapMixinsType<PublicMixin, 'P'> & EnsureNonVoid<P>,
PublicB = UnwrapMixinsType<PublicMixin, 'B'> & EnsureNonVoid<B>,
PublicC extends ComputedOptions = UnwrapMixinsType<PublicMixin, 'C'> &
EnsureNonVoid<C>,
PublicM extends MethodOptions = UnwrapMixinsType<PublicMixin, 'M'> &
- EnsureNonVoid<M>
+ EnsureNonVoid<M>,
+ PublicDefaults = UnwrapMixinsType<PublicMixin, 'Defaults'> &
+ EnsureNonVoid<Defaults>
> = ComponentPublicInstance<
PublicP,
PublicB,
PublicM,
E,
PublicProps,
- ComponentOptionsBase<P, B, D, C, M, Mixin, Extends, E>
+ PublicDefaults,
+ MakeDefaultsOptional,
+ ComponentOptionsBase<P, B, D, C, M, Mixin, Extends, E, string, Defaults>
>
// public properties exposed on the proxy, which is used as the render context
M extends MethodOptions = {},
E extends EmitsOptions = {},
PublicProps = P,
- Options = ComponentOptionsBase<any, any, any, any, any, any, any, any>
+ Defaults = {},
+ MakeDefaultsOptional extends boolean = false,
+ Options = ComponentOptionsBase<any, any, any, any, any, any, any, any, any>
> = {
$: ComponentInternalInstance
$data: D
- $props: P & PublicProps
+ $props: MakeDefaultsOptional extends true
+ ? Partial<Defaults> & Omit<P & PublicProps, keyof Defaults>
+ : P & PublicProps
$attrs: Data
$refs: Data
$slots: Slots
} from './apiLifecycle'
export { provide, inject } from './apiInject'
export { nextTick } from './scheduler'
-export { defineComponent, DefineComponent } from './apiDefineComponent'
+export { defineComponent } from './apiDefineComponent'
export { defineAsyncComponent } from './apiAsyncComponent'
// Advanced API ----------------------------------------------------------------
ComponentCustomProps,
AllowedComponentProps
} from './component'
+export { DefineComponent } from './apiDefineComponent'
export {
ComponentOptions,
ComponentOptionsMixin,
PropType,
ComponentPropsOptions,
ComponentObjectPropsOptions,
- ExtractPropTypes
+ ExtractPropTypes,
+ ExtractDefaultPropTypes
} from './componentProps'
export {
Directive,
type: String,
default: 'mP1'
},
- mP2: Boolean
+ mP2: Boolean,
+ mP3: {
+ type: Boolean,
+ required: true
+ }
},
data() {
return {
p2: {
type: Number,
default: 2
+ },
+ p3: {
+ type: Boolean,
+ required: true
}
},
data() {
})
// Test TSX
- expectType<JSX.Element>(<MyComponent mP1="p1" mP2 p1 p2={1} z={'z'} />)
+ expectType<JSX.Element>(<MyComponent mP1="p1" mP2 mP3 p1 p2={1} p3 z={'z'} />)
+
+ // mP1, mP2, p1, and p2 have default value. these are not required
+ expectType<JSX.Element>(<MyComponent mP3 p3 z={'z'} />)
// missing required props
// @ts-expect-error
- expectError(<MyComponent />)
+ expectError(<MyComponent mP3 p3 /* z='z' */ />)
+ // missing required props from mixin
+ // @ts-expect-error
+ expectError(<MyComponent /* mP3 */ p3 z="z" />)
+ // missing required props from extends
+ // @ts-expect-error
+ expectError(<MyComponent mP3 /* p3 */ z="z" />)
// wrong prop types
// @ts-expect-error