]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
types(defineComponent): fix optional Boolean prop types (#2401)
authorCarlos Rodrigues <david-181@hotmail.com>
Mon, 19 Oct 2020 21:25:55 +0000 (22:25 +0100)
committerGitHub <noreply@github.com>
Mon, 19 Oct 2020 21:25:55 +0000 (17:25 -0400)
fix #2338

packages/runtime-core/src/componentProps.ts
test-dts/defineComponent.test-d.tsx
test-dts/h.test-d.ts

index 938318d4a9f929743e35e5d8358684814a665450..f1be9b76961e6a11b7f88d6f10a1d6fc29d1d1c0 100644 (file)
@@ -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
index f201d660d87296af592423a470543274d6fbe2f5..c77feba025d37c1160766e01d6f469499b3a0184 100644 (file)
@@ -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)
index 4376eaf979e201cd5d3668a31d814d15111cc414..877c62860cdf5baba809f6802a51553cea1a499f 100644 (file)
@@ -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, {}))
+})