Просмотр исходного кода

types(defineComponent): fix optional Boolean prop types (#2401)

fix #2338
Carlos Rodrigues 5 лет назад
Родитель
Сommit
d9ad45ad6c

+ 17 - 2
packages/runtime-core/src/componentProps.ts

@@ -65,13 +65,28 @@ type PropMethod<T, TConstructor = any> = T extends (...args: any) => any // if i
   : never
 
 type RequiredKeys<T> = {
-  [K in keyof T]: T[K] extends { required: true } | { default: any } ? K : never
+  [K in keyof T]: T[K] extends
+    | { required: true }
+    | { default: any }
+    // don't mark Boolean props as undefined
+    | BooleanConstructor
+    | { type: BooleanConstructor }
+    ? K
+    : never
 }[keyof T]
 
 type OptionalKeys<T> = Exclude<keyof T, RequiredKeys<T>>
 
 type DefaultKeys<T> = {
-  [K in keyof T]: T[K] extends { default: any } ? K : never
+  [K in keyof T]: T[K] extends
+    | { default: any }
+    // Boolean implicitly defaults to false
+    | BooleanConstructor
+    | { type: BooleanConstructor }
+    ? T[K] extends { type: BooleanConstructor; required: true } // not default if Boolean is marked as required
+      ? never
+      : K
+    : never
 }[keyof T]
 
 type InferPropType<T> = T extends null

+ 5 - 0
test-dts/defineComponent.test-d.tsx

@@ -19,6 +19,7 @@ describe('with object props', () => {
     a?: number | undefined
     b: string
     e?: Function
+    h: boolean
     bb: string
     bbb: string
     cc?: string[] | undefined
@@ -46,6 +47,7 @@ describe('with object props', () => {
         required: true
       },
       e: Function,
+      h: Boolean,
       // default value should infer type and make it non-void
       bb: {
         default: 'hello'
@@ -108,6 +110,7 @@ describe('with object props', () => {
       expectType<ExpectedProps['a']>(props.a)
       expectType<ExpectedProps['b']>(props.b)
       expectType<ExpectedProps['e']>(props.e)
+      expectType<ExpectedProps['h']>(props.h)
       expectType<ExpectedProps['bb']>(props.bb)
       expectType<ExpectedProps['bbb']>(props.bbb)
       expectType<ExpectedProps['cc']>(props.cc)
@@ -142,6 +145,7 @@ describe('with object props', () => {
       expectType<ExpectedProps['a']>(props.a)
       expectType<ExpectedProps['b']>(props.b)
       expectType<ExpectedProps['e']>(props.e)
+      expectType<ExpectedProps['h']>(props.h)
       expectType<ExpectedProps['bb']>(props.bb)
       expectType<ExpectedProps['cc']>(props.cc)
       expectType<ExpectedProps['dd']>(props.dd)
@@ -161,6 +165,7 @@ describe('with object props', () => {
       expectType<ExpectedProps['a']>(this.a)
       expectType<ExpectedProps['b']>(this.b)
       expectType<ExpectedProps['e']>(this.e)
+      expectType<ExpectedProps['h']>(this.h)
       expectType<ExpectedProps['bb']>(this.bb)
       expectType<ExpectedProps['cc']>(this.cc)
       expectType<ExpectedProps['dd']>(this.dd)

+ 26 - 0
test-dts/h.test-d.ts

@@ -198,3 +198,29 @@ describe('component w/ props w/ default value', () => {
 
   h(MyComponent, {})
 })
+
+// #2338
+describe('Boolean prop implicit false', () => {
+  const MyComponent = defineComponent({
+    props: {
+      visible: Boolean
+    }
+  })
+
+  h(MyComponent, {})
+
+  const RequiredComponent = defineComponent({
+    props: {
+      visible: {
+        type: Boolean,
+        required: true
+      }
+    }
+  })
+
+  h(RequiredComponent, {
+    visible: true
+  })
+  // @ts-expect-error
+  expectError(h(RequiredComponent, {}))
+})