Skip to content

Commit 89e9ab8

Browse files
fix(types/tsx): optional props from Mixin/Extends are treated as required (#2048)
1 parent 7e68ddd commit 89e9ab8

File tree

6 files changed

+133
-46
lines changed

6 files changed

+133
-46
lines changed

packages/runtime-core/src/apiDefineComponent.ts

+15-8
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@ import {
1313
AllowedComponentProps,
1414
ComponentCustomProps
1515
} from './component'
16-
import { ExtractPropTypes, ComponentPropsOptions } from './componentProps'
16+
import {
17+
ExtractPropTypes,
18+
ComponentPropsOptions,
19+
ExtractDefaultPropTypes
20+
} from './componentProps'
1721
import { EmitsOptions } from './componentEmits'
1822
import { isFunction } from '@vue/shared'
1923
import { VNodeProps } from './vnode'
@@ -37,32 +41,35 @@ export type DefineComponent<
3741
E extends EmitsOptions = Record<string, any>,
3842
EE extends string = string,
3943
PP = PublicProps,
40-
RequiredProps = Readonly<ExtractPropTypes<PropsOrPropOptions>>,
41-
OptionalProps = Readonly<ExtractPropTypes<PropsOrPropOptions, false>>
44+
Props = Readonly<ExtractPropTypes<PropsOrPropOptions>>,
45+
Defaults = ExtractDefaultPropTypes<PropsOrPropOptions>
4246
> = ComponentPublicInstanceConstructor<
4347
CreateComponentPublicInstance<
44-
OptionalProps,
48+
Props,
4549
RawBindings,
4650
D,
4751
C,
4852
M,
4953
Mixin,
5054
Extends,
5155
E,
52-
PP & OptionalProps
56+
PP & Props,
57+
Defaults,
58+
true
5359
> &
54-
RequiredProps
60+
Props
5561
> &
5662
ComponentOptionsBase<
57-
RequiredProps,
63+
Props,
5864
RawBindings,
5965
D,
6066
C,
6167
M,
6268
Mixin,
6369
Extends,
6470
E,
65-
EE
71+
EE,
72+
Defaults
6673
> &
6774
PP
6875

packages/runtime-core/src/componentOptions.ts

+61-11
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,11 @@ import {
4242
WritableComputedOptions,
4343
toRaw
4444
} from '@vue/reactivity'
45-
import { ComponentObjectPropsOptions, ExtractPropTypes } from './componentProps'
45+
import {
46+
ComponentObjectPropsOptions,
47+
ExtractPropTypes,
48+
ExtractDefaultPropTypes
49+
} from './componentProps'
4650
import { EmitsOptions } from './componentEmits'
4751
import { Directive } from './directives'
4852
import {
@@ -81,7 +85,8 @@ export interface ComponentOptionsBase<
8185
Mixin extends ComponentOptionsMixin,
8286
Extends extends ComponentOptionsMixin,
8387
E extends EmitsOptions,
84-
EE extends string = string
88+
EE extends string = string,
89+
Defaults = {}
8590
>
8691
extends LegacyOptions<Props, D, C, M, Mixin, Extends>,
8792
ComponentInternalOptions,
@@ -148,6 +153,8 @@ export interface ComponentOptionsBase<
148153
__isFragment?: never
149154
__isTeleport?: never
150155
__isSuspense?: never
156+
157+
__defaults?: Defaults
151158
}
152159

153160
export type ComponentOptionsWithoutProps<
@@ -159,8 +166,20 @@ export type ComponentOptionsWithoutProps<
159166
Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
160167
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
161168
E extends EmitsOptions = EmitsOptions,
162-
EE extends string = string
163-
> = ComponentOptionsBase<Props, RawBindings, D, C, M, Mixin, Extends, E, EE> & {
169+
EE extends string = string,
170+
Defaults = {}
171+
> = ComponentOptionsBase<
172+
Props,
173+
RawBindings,
174+
D,
175+
C,
176+
M,
177+
Mixin,
178+
Extends,
179+
E,
180+
EE,
181+
Defaults
182+
> & {
164183
props?: undefined
165184
} & ThisType<
166185
CreateComponentPublicInstance<
@@ -172,7 +191,9 @@ export type ComponentOptionsWithoutProps<
172191
Mixin,
173192
Extends,
174193
E,
175-
Readonly<Props>
194+
Readonly<Props>,
195+
Defaults,
196+
false
176197
>
177198
>
178199

@@ -187,7 +208,18 @@ export type ComponentOptionsWithArrayProps<
187208
E extends EmitsOptions = EmitsOptions,
188209
EE extends string = string,
189210
Props = Readonly<{ [key in PropNames]?: any }>
190-
> = ComponentOptionsBase<Props, RawBindings, D, C, M, Mixin, Extends, E, EE> & {
211+
> = ComponentOptionsBase<
212+
Props,
213+
RawBindings,
214+
D,
215+
C,
216+
M,
217+
Mixin,
218+
Extends,
219+
E,
220+
EE,
221+
{}
222+
> & {
191223
props: PropNames[]
192224
} & ThisType<
193225
CreateComponentPublicInstance<
@@ -212,8 +244,20 @@ export type ComponentOptionsWithObjectProps<
212244
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
213245
E extends EmitsOptions = EmitsOptions,
214246
EE extends string = string,
215-
Props = Readonly<ExtractPropTypes<PropsOptions>>
216-
> = ComponentOptionsBase<Props, RawBindings, D, C, M, Mixin, Extends, E, EE> & {
247+
Props = Readonly<ExtractPropTypes<PropsOptions>>,
248+
Defaults = ExtractDefaultPropTypes<PropsOptions>
249+
> = ComponentOptionsBase<
250+
Props,
251+
RawBindings,
252+
D,
253+
C,
254+
M,
255+
Mixin,
256+
Extends,
257+
E,
258+
EE,
259+
Defaults
260+
> & {
217261
props: PropsOptions & ThisType<void>
218262
} & ThisType<
219263
CreateComponentPublicInstance<
@@ -224,7 +268,10 @@ export type ComponentOptionsWithObjectProps<
224268
M,
225269
Mixin,
226270
Extends,
227-
E
271+
E,
272+
Props,
273+
Defaults,
274+
false
228275
>
229276
>
230277

@@ -261,6 +308,7 @@ export type ComponentOptionsMixin = ComponentOptionsBase<
261308
any,
262309
any,
263310
any,
311+
any,
264312
any
265313
>
266314

@@ -347,20 +395,22 @@ interface LegacyOptions<
347395
delimiters?: [string, string]
348396
}
349397

350-
export type OptionTypesKeys = 'P' | 'B' | 'D' | 'C' | 'M'
398+
export type OptionTypesKeys = 'P' | 'B' | 'D' | 'C' | 'M' | 'Defaults'
351399

352400
export type OptionTypesType<
353401
P = {},
354402
B = {},
355403
D = {},
356404
C extends ComputedOptions = {},
357-
M extends MethodOptions = {}
405+
M extends MethodOptions = {},
406+
Defaults = {}
358407
> = {
359408
P: P
360409
B: B
361410
D: D
362411
C: C
363412
M: M
413+
Defaults: Defaults
364414
}
365415

366416
const enum OptionTypes {

packages/runtime-core/src/componentProps.ts

+15-16
Original file line numberDiff line numberDiff line change
@@ -63,18 +63,15 @@ type PropMethod<T, TConstructor = any> = T extends (...args: any) => any // if i
6363
? { new (): TConstructor; (): T; readonly prototype: TConstructor } // Create Function like constructor
6464
: never
6565

66-
type RequiredKeys<T, MakeDefaultRequired> = {
67-
[K in keyof T]: T[K] extends
68-
| { required: true }
69-
| (MakeDefaultRequired extends true ? { default: any } : never)
70-
? K
71-
: never
66+
type RequiredKeys<T> = {
67+
[K in keyof T]: T[K] extends { required: true } | { default: any } ? K : never
7268
}[keyof T]
7369

74-
type OptionalKeys<T, MakeDefaultRequired> = Exclude<
75-
keyof T,
76-
RequiredKeys<T, MakeDefaultRequired>
77-
>
70+
type OptionalKeys<T> = Exclude<keyof T, RequiredKeys<T>>
71+
72+
type DefaultKeys<T> = {
73+
[K in keyof T]: T[K] extends { default: any } ? K : never
74+
}[keyof T]
7875

7976
type InferPropType<T> = T extends null
8077
? any // null & true would fail to infer
@@ -86,19 +83,21 @@ type InferPropType<T> = T extends null
8683
? boolean
8784
: T extends Prop<infer V, infer D> ? (unknown extends V ? D : V) : T
8885

89-
export type ExtractPropTypes<
90-
O,
91-
MakeDefaultRequired extends boolean = true
92-
> = O extends object
93-
? { [K in RequiredKeys<O, MakeDefaultRequired>]: InferPropType<O[K]> } &
94-
{ [K in OptionalKeys<O, MakeDefaultRequired>]?: InferPropType<O[K]> }
86+
export type ExtractPropTypes<O> = O extends object
87+
? { [K in RequiredKeys<O>]: InferPropType<O[K]> } &
88+
{ [K in OptionalKeys<O>]?: InferPropType<O[K]> }
9589
: { [K in string]: any }
9690

9791
const enum BooleanFlags {
9892
shouldCast,
9993
shouldCastTrue
10094
}
10195

96+
// extract props which defined with default from prop options
97+
export type ExtractDefaultPropTypes<O> = O extends object
98+
? { [K in DefaultKeys<O>]: InferPropType<O[K]> }
99+
: {}
100+
102101
type NormalizedProp =
103102
| null
104103
| (PropOptions & {

packages/runtime-core/src/componentPublicInstance.ts

+18-6
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,11 @@ type MixinToOptionTypes<T> = T extends ComponentOptionsBase<
7777
infer M,
7878
infer Mixin,
7979
infer Extends,
80-
any
80+
any,
81+
any,
82+
infer Defaults
8183
>
82-
? OptionTypesType<P & {}, B & {}, D & {}, C & {}, M & {}> &
84+
? OptionTypesType<P & {}, B & {}, D & {}, C & {}, M & {}, Defaults & {}> &
8385
IntersectionMixin<Mixin> &
8486
IntersectionMixin<Extends>
8587
: never
@@ -130,14 +132,18 @@ export type CreateComponentPublicInstance<
130132
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
131133
E extends EmitsOptions = {},
132134
PublicProps = P,
135+
Defaults = {},
136+
MakeDefaultsOptional extends boolean = false,
133137
PublicMixin = IntersectionMixin<Mixin> & IntersectionMixin<Extends>,
134138
PublicP = UnwrapMixinsType<PublicMixin, 'P'> & EnsureNonVoid<P>,
135139
PublicB = UnwrapMixinsType<PublicMixin, 'B'> & EnsureNonVoid<B>,
136140
PublicD = UnwrapMixinsType<PublicMixin, 'D'> & EnsureNonVoid<D>,
137141
PublicC extends ComputedOptions = UnwrapMixinsType<PublicMixin, 'C'> &
138142
EnsureNonVoid<C>,
139143
PublicM extends MethodOptions = UnwrapMixinsType<PublicMixin, 'M'> &
140-
EnsureNonVoid<M>
144+
EnsureNonVoid<M>,
145+
PublicDefaults = UnwrapMixinsType<PublicMixin, 'Defaults'> &
146+
EnsureNonVoid<Defaults>
141147
> = ComponentPublicInstance<
142148
PublicP,
143149
PublicB,
@@ -146,7 +152,9 @@ export type CreateComponentPublicInstance<
146152
PublicM,
147153
E,
148154
PublicProps,
149-
ComponentOptionsBase<P, B, D, C, M, Mixin, Extends, E>
155+
PublicDefaults,
156+
MakeDefaultsOptional,
157+
ComponentOptionsBase<P, B, D, C, M, Mixin, Extends, E, string, Defaults>
150158
>
151159

152160
// public properties exposed on the proxy, which is used as the render context
@@ -159,11 +167,15 @@ export type ComponentPublicInstance<
159167
M extends MethodOptions = {},
160168
E extends EmitsOptions = {},
161169
PublicProps = P,
162-
Options = ComponentOptionsBase<any, any, any, any, any, any, any, any>
170+
Defaults = {},
171+
MakeDefaultsOptional extends boolean = false,
172+
Options = ComponentOptionsBase<any, any, any, any, any, any, any, any, any>
163173
> = {
164174
$: ComponentInternalInstance
165175
$data: D
166-
$props: P & PublicProps
176+
$props: MakeDefaultsOptional extends true
177+
? Partial<Defaults> & Omit<P & PublicProps, keyof Defaults>
178+
: P & PublicProps
167179
$attrs: Data
168180
$refs: Data
169181
$slots: Slots

packages/runtime-core/src/index.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export {
4141
} from './apiLifecycle'
4242
export { provide, inject } from './apiInject'
4343
export { nextTick } from './scheduler'
44-
export { defineComponent, DefineComponent } from './apiDefineComponent'
44+
export { defineComponent } from './apiDefineComponent'
4545
export { defineAsyncComponent } from './apiAsyncComponent'
4646

4747
// Advanced API ----------------------------------------------------------------
@@ -166,6 +166,7 @@ export {
166166
ComponentCustomProps,
167167
AllowedComponentProps
168168
} from './component'
169+
export { DefineComponent } from './apiDefineComponent'
169170
export {
170171
ComponentOptions,
171172
ComponentOptionsMixin,
@@ -198,7 +199,8 @@ export {
198199
PropType,
199200
ComponentPropsOptions,
200201
ComponentObjectPropsOptions,
201-
ExtractPropTypes
202+
ExtractPropTypes,
203+
ExtractDefaultPropTypes
202204
} from './componentProps'
203205
export {
204206
Directive,

0 commit comments

Comments
 (0)