]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(types): allow use PropType with Function (#915)
authorCarlos Rodrigues <carlos@hypermob.co.uk>
Fri, 3 Apr 2020 13:28:13 +0000 (14:28 +0100)
committerGitHub <noreply@github.com>
Fri, 3 Apr 2020 13:28:13 +0000 (09:28 -0400)
close #748

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

index f9de525c87d64d8a68ebc1ac81e69f6a75705c41..61f968b76342685d24f8a00c027894537c488280 100644 (file)
@@ -39,7 +39,14 @@ interface PropOptions<T = any> {
 
 export type PropType<T> = PropConstructor<T> | PropConstructor<T>[]
 
-type PropConstructor<T = any> = { new (...args: any[]): T & object } | { (): T }
+type PropConstructor<T = any> =
+  | { new (...args: any[]): T & object }
+  | { (): T }
+  | PropMethod<T>
+
+type PropMethod<T> = T extends (...args: any) => any // if is function with args
+  ? { new (): T; (): T; readonly proptotype: Function } // Create Function like contructor
+  : never
 
 type RequiredKeys<T, MakeDefaultRequired> = {
   [K in keyof T]: T[K] extends
index 33f55695569b5eb756e4a6856826dc24ec1886b7..6838e6db2fc365406c480730cc36f886f0b8e3db 100644 (file)
@@ -12,11 +12,16 @@ describe('with object props', () => {
   interface ExpectedProps {
     a?: number | undefined
     b: string
+    e?: Function
     bb: string
     cc?: string[] | undefined
     dd: string[]
+    ee?: () => string
+    ff?: (a: number, b: string) => { a: boolean }
     ccc?: string[] | undefined
     ddd: string[]
+    eee: () => { a: string }
+    fff: (a: number, b: string) => { a: boolean }
   }
 
   type GT = string & { __brand: unknown }
@@ -29,6 +34,7 @@ describe('with object props', () => {
         type: String,
         required: true
       },
+      e: Function,
       // default value should infer type and make it non-void
       bb: {
         default: 'hello'
@@ -40,23 +46,42 @@ describe('with object props', () => {
         type: Array as PropType<string[]>,
         required: true
       },
+      // return type
+      ee: Function as PropType<() => string>,
+      // arguments + object return
+      ff: Function as PropType<(a: number, b: string) => { a: boolean }>,
       // explicit type casting with constructor
       ccc: Array as () => string[],
       // required + contructor type casting
       ddd: {
         type: Array as () => string[],
         required: true
+      },
+      // required + object return
+      eee: {
+        type: Function as PropType<() => { a: string }>,
+        required: true
+      },
+      // required + arguments + object return
+      fff: {
+        type: Function as PropType<(a: number, b: string) => { a: boolean }>,
+        required: true
       }
     },
     setup(props) {
       // type assertion. See https://github.com/SamVerschueren/tsd
       expectType<ExpectedProps['a']>(props.a)
       expectType<ExpectedProps['b']>(props.b)
+      expectType<ExpectedProps['e']>(props.e)
       expectType<ExpectedProps['bb']>(props.bb)
       expectType<ExpectedProps['cc']>(props.cc)
       expectType<ExpectedProps['dd']>(props.dd)
+      expectType<ExpectedProps['ee']>(props.ee)
+      expectType<ExpectedProps['ff']>(props.ff)
       expectType<ExpectedProps['ccc']>(props.ccc)
       expectType<ExpectedProps['ddd']>(props.ddd)
+      expectType<ExpectedProps['eee']>(props.eee)
+      expectType<ExpectedProps['fff']>(props.fff)
 
       // props should be readonly
       expectError((props.a = 1))
@@ -76,11 +101,16 @@ describe('with object props', () => {
       const props = this.$props
       expectType<ExpectedProps['a']>(props.a)
       expectType<ExpectedProps['b']>(props.b)
+      expectType<ExpectedProps['e']>(props.e)
       expectType<ExpectedProps['bb']>(props.bb)
       expectType<ExpectedProps['cc']>(props.cc)
       expectType<ExpectedProps['dd']>(props.dd)
+      expectType<ExpectedProps['ee']>(props.ee)
+      expectType<ExpectedProps['ff']>(props.ff)
       expectType<ExpectedProps['ccc']>(props.ccc)
       expectType<ExpectedProps['ddd']>(props.ddd)
+      expectType<ExpectedProps['eee']>(props.eee)
+      expectType<ExpectedProps['fff']>(props.fff)
 
       // props should be readonly
       expectError((props.a = 1))
@@ -88,11 +118,16 @@ describe('with object props', () => {
       // should also expose declared props on `this`
       expectType<ExpectedProps['a']>(this.a)
       expectType<ExpectedProps['b']>(this.b)
+      expectType<ExpectedProps['e']>(this.e)
       expectType<ExpectedProps['bb']>(this.bb)
       expectType<ExpectedProps['cc']>(this.cc)
       expectType<ExpectedProps['dd']>(this.dd)
+      expectType<ExpectedProps['ee']>(this.ee)
+      expectType<ExpectedProps['ff']>(this.ff)
       expectType<ExpectedProps['ccc']>(this.ccc)
       expectType<ExpectedProps['ddd']>(this.ddd)
+      expectType<ExpectedProps['eee']>(this.eee)
+      expectType<ExpectedProps['fff']>(this.fff)
 
       // props on `this` should be readonly
       expectError((this.a = 1))
@@ -115,10 +150,14 @@ describe('with object props', () => {
       a={1}
       b="b"
       bb="bb"
+      e={() => {}}
       cc={['cc']}
       dd={['dd']}
+      ee={() => 'ee'}
       ccc={['ccc']}
       ddd={['ddd']}
+      eee={() => ({ a: 'eee' })}
+      fff={(a, b) => ({ a: a > +b })}
       // should allow extraneous as attrs
       class="bar"
       // should allow key