Skip to content

Commit d9ad45a

Browse files
authored
types(defineComponent): fix optional Boolean prop types (#2401)
fix #2338
1 parent 8e5cdc0 commit d9ad45a

File tree

3 files changed

+48
-2
lines changed

3 files changed

+48
-2
lines changed

packages/runtime-core/src/componentProps.ts

+17-2
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,28 @@ type PropMethod<T, TConstructor = any> = T extends (...args: any) => any // if i
6565
: never
6666

6767
type RequiredKeys<T> = {
68-
[K in keyof T]: T[K] extends { required: true } | { default: any } ? K : never
68+
[K in keyof T]: T[K] extends
69+
| { required: true }
70+
| { default: any }
71+
// don't mark Boolean props as undefined
72+
| BooleanConstructor
73+
| { type: BooleanConstructor }
74+
? K
75+
: never
6976
}[keyof T]
7077

7178
type OptionalKeys<T> = Exclude<keyof T, RequiredKeys<T>>
7279

7380
type DefaultKeys<T> = {
74-
[K in keyof T]: T[K] extends { default: any } ? K : never
81+
[K in keyof T]: T[K] extends
82+
| { default: any }
83+
// Boolean implicitly defaults to false
84+
| BooleanConstructor
85+
| { type: BooleanConstructor }
86+
? T[K] extends { type: BooleanConstructor; required: true } // not default if Boolean is marked as required
87+
? never
88+
: K
89+
: never
7590
}[keyof T]
7691

7792
type InferPropType<T> = T extends null

test-dts/defineComponent.test-d.tsx

+5
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ describe('with object props', () => {
1919
a?: number | undefined
2020
b: string
2121
e?: Function
22+
h: boolean
2223
bb: string
2324
bbb: string
2425
cc?: string[] | undefined
@@ -46,6 +47,7 @@ describe('with object props', () => {
4647
required: true
4748
},
4849
e: Function,
50+
h: Boolean,
4951
// default value should infer type and make it non-void
5052
bb: {
5153
default: 'hello'
@@ -108,6 +110,7 @@ describe('with object props', () => {
108110
expectType<ExpectedProps['a']>(props.a)
109111
expectType<ExpectedProps['b']>(props.b)
110112
expectType<ExpectedProps['e']>(props.e)
113+
expectType<ExpectedProps['h']>(props.h)
111114
expectType<ExpectedProps['bb']>(props.bb)
112115
expectType<ExpectedProps['bbb']>(props.bbb)
113116
expectType<ExpectedProps['cc']>(props.cc)
@@ -142,6 +145,7 @@ describe('with object props', () => {
142145
expectType<ExpectedProps['a']>(props.a)
143146
expectType<ExpectedProps['b']>(props.b)
144147
expectType<ExpectedProps['e']>(props.e)
148+
expectType<ExpectedProps['h']>(props.h)
145149
expectType<ExpectedProps['bb']>(props.bb)
146150
expectType<ExpectedProps['cc']>(props.cc)
147151
expectType<ExpectedProps['dd']>(props.dd)
@@ -161,6 +165,7 @@ describe('with object props', () => {
161165
expectType<ExpectedProps['a']>(this.a)
162166
expectType<ExpectedProps['b']>(this.b)
163167
expectType<ExpectedProps['e']>(this.e)
168+
expectType<ExpectedProps['h']>(this.h)
164169
expectType<ExpectedProps['bb']>(this.bb)
165170
expectType<ExpectedProps['cc']>(this.cc)
166171
expectType<ExpectedProps['dd']>(this.dd)

test-dts/h.test-d.ts

+26
Original file line numberDiff line numberDiff line change
@@ -198,3 +198,29 @@ describe('component w/ props w/ default value', () => {
198198

199199
h(MyComponent, {})
200200
})
201+
202+
// #2338
203+
describe('Boolean prop implicit false', () => {
204+
const MyComponent = defineComponent({
205+
props: {
206+
visible: Boolean
207+
}
208+
})
209+
210+
h(MyComponent, {})
211+
212+
const RequiredComponent = defineComponent({
213+
props: {
214+
visible: {
215+
type: Boolean,
216+
required: true
217+
}
218+
}
219+
})
220+
221+
h(RequiredComponent, {
222+
visible: true
223+
})
224+
// @ts-expect-error
225+
expectError(h(RequiredComponent, {}))
226+
})

0 commit comments

Comments
 (0)