]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
types(runtime-core): improve PropType inference precision (#1863)
authorHcySunYang <HcySunYang@outlook.com>
Tue, 18 Aug 2020 15:23:18 +0000 (23:23 +0800)
committerGitHub <noreply@github.com>
Tue, 18 Aug 2020 15:23:18 +0000 (11:23 -0400)
packages/runtime-core/src/componentProps.ts
test-dts/defineComponent.test-d.tsx

index fcf707e021ce4d77e9affc3326526aec6f763ae2..9e6540cfa1c56408b254a8d9bf868bde116a77a3 100644 (file)
@@ -40,14 +40,14 @@ export type ComponentObjectPropsOptions<P = Data> = {
   [K in keyof P]: Prop<P[K]> | null
 }
 
-export type Prop<T> = PropOptions<T> | PropType<T>
+export type Prop<T, D = T> = PropOptions<T, D> | PropType<T>
 
 type DefaultFactory<T> = () => T | null | undefined
 
-interface PropOptions<T = any> {
+interface PropOptions<T = any, D = T> {
   type?: PropType<T> | true | null
   required?: boolean
-  default?: T | DefaultFactory<T> | null | undefined
+  default?: D | DefaultFactory<D> | null | undefined
   validator?(value: unknown): boolean
 }
 
@@ -83,7 +83,7 @@ type InferPropType<T> = T extends null
       ? Record<string, any>
       : T extends BooleanConstructor | { type: BooleanConstructor }
         ? boolean
-        : T extends Prop<infer V> ? V : T
+        : T extends Prop<infer V, infer D> ? (unknown extends V ? D : V) : T
 
 export type ExtractPropTypes<
   O,
index b65ca88ae89d982f0f95e08a7bda1e9cebea942d..1dbb192914508ff27f494c16639beb82a5d4b8c6 100644 (file)
@@ -27,6 +27,7 @@ describe('with object props', () => {
     eee: () => { a: string }
     fff: (a: number, b: string) => { a: boolean }
     hhh: boolean
+    ggg: 'foo' | 'bar'
     validated?: string
   }
 
@@ -77,6 +78,11 @@ describe('with object props', () => {
         type: Boolean,
         required: true
       },
+      // default + type casting
+      ggg: {
+        type: String as PropType<'foo' | 'bar'>,
+        default: 'foo'
+      },
       validated: {
         type: String,
         validator: (val: unknown) => val !== ''
@@ -97,6 +103,7 @@ describe('with object props', () => {
       expectType<ExpectedProps['eee']>(props.eee)
       expectType<ExpectedProps['fff']>(props.fff)
       expectType<ExpectedProps['hhh']>(props.hhh)
+      expectType<ExpectedProps['ggg']>(props.ggg)
       expectType<ExpectedProps['validated']>(props.validated)
 
       // @ts-expect-error props should be readonly
@@ -128,6 +135,7 @@ describe('with object props', () => {
       expectType<ExpectedProps['eee']>(props.eee)
       expectType<ExpectedProps['fff']>(props.fff)
       expectType<ExpectedProps['hhh']>(props.hhh)
+      expectType<ExpectedProps['ggg']>(props.ggg)
 
       // @ts-expect-error props should be readonly
       expectError((props.a = 1))
@@ -146,6 +154,7 @@ describe('with object props', () => {
       expectType<ExpectedProps['eee']>(this.eee)
       expectType<ExpectedProps['fff']>(this.fff)
       expectType<ExpectedProps['hhh']>(this.hhh)
+      expectType<ExpectedProps['ggg']>(this.ggg)
 
       // @ts-expect-error props on `this` should be readonly
       expectError((this.a = 1))
@@ -177,6 +186,7 @@ describe('with object props', () => {
       eee={() => ({ a: 'eee' })}
       fff={(a, b) => ({ a: a > +b })}
       hhh={false}
+      ggg="foo"
       // should allow class/style as attrs
       class="bar"
       style={{ color: 'red' }}
@@ -194,6 +204,10 @@ describe('with object props', () => {
     // @ts-expect-error wrong prop types
     <MyComponent a={'wrong type'} b="foo" dd={{ n: 1 }} ddd={['foo']} />
   )
+  expectError(
+    // @ts-expect-error wrong prop types
+    <MyComponent ggg="baz" />
+  )
   // @ts-expect-error
   expectError(<MyComponent b="foo" dd={{ n: 'string' }} ddd={['foo']} />)
 })