fix(types): allow use PropType with Function (#915)

close #748
This commit is contained in:
Carlos Rodrigues 2020-04-03 14:28:13 +01:00 committed by GitHub
parent 4b03b922e2
commit 026eb729f3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 47 additions and 1 deletions

View File

@ -39,7 +39,14 @@ interface PropOptions<T = any> {
export type PropType<T> = PropConstructor<T> | PropConstructor<T>[] 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> = { type RequiredKeys<T, MakeDefaultRequired> = {
[K in keyof T]: T[K] extends [K in keyof T]: T[K] extends

View File

@ -12,11 +12,16 @@ describe('with object props', () => {
interface ExpectedProps { interface ExpectedProps {
a?: number | undefined a?: number | undefined
b: string b: string
e?: Function
bb: string bb: string
cc?: string[] | undefined cc?: string[] | undefined
dd: string[] dd: string[]
ee?: () => string
ff?: (a: number, b: string) => { a: boolean }
ccc?: string[] | undefined ccc?: string[] | undefined
ddd: string[] ddd: string[]
eee: () => { a: string }
fff: (a: number, b: string) => { a: boolean }
} }
type GT = string & { __brand: unknown } type GT = string & { __brand: unknown }
@ -29,6 +34,7 @@ describe('with object props', () => {
type: String, type: String,
required: true required: true
}, },
e: Function,
// default value should infer type and make it non-void // default value should infer type and make it non-void
bb: { bb: {
default: 'hello' default: 'hello'
@ -40,23 +46,42 @@ describe('with object props', () => {
type: Array as PropType<string[]>, type: Array as PropType<string[]>,
required: true 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 // explicit type casting with constructor
ccc: Array as () => string[], ccc: Array as () => string[],
// required + contructor type casting // required + contructor type casting
ddd: { ddd: {
type: Array as () => string[], type: Array as () => string[],
required: true 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) { setup(props) {
// type assertion. See https://github.com/SamVerschueren/tsd // type assertion. See https://github.com/SamVerschueren/tsd
expectType<ExpectedProps['a']>(props.a) expectType<ExpectedProps['a']>(props.a)
expectType<ExpectedProps['b']>(props.b) expectType<ExpectedProps['b']>(props.b)
expectType<ExpectedProps['e']>(props.e)
expectType<ExpectedProps['bb']>(props.bb) expectType<ExpectedProps['bb']>(props.bb)
expectType<ExpectedProps['cc']>(props.cc) expectType<ExpectedProps['cc']>(props.cc)
expectType<ExpectedProps['dd']>(props.dd) expectType<ExpectedProps['dd']>(props.dd)
expectType<ExpectedProps['ee']>(props.ee)
expectType<ExpectedProps['ff']>(props.ff)
expectType<ExpectedProps['ccc']>(props.ccc) expectType<ExpectedProps['ccc']>(props.ccc)
expectType<ExpectedProps['ddd']>(props.ddd) expectType<ExpectedProps['ddd']>(props.ddd)
expectType<ExpectedProps['eee']>(props.eee)
expectType<ExpectedProps['fff']>(props.fff)
// props should be readonly // props should be readonly
expectError((props.a = 1)) expectError((props.a = 1))
@ -76,11 +101,16 @@ describe('with object props', () => {
const props = this.$props const props = this.$props
expectType<ExpectedProps['a']>(props.a) expectType<ExpectedProps['a']>(props.a)
expectType<ExpectedProps['b']>(props.b) expectType<ExpectedProps['b']>(props.b)
expectType<ExpectedProps['e']>(props.e)
expectType<ExpectedProps['bb']>(props.bb) expectType<ExpectedProps['bb']>(props.bb)
expectType<ExpectedProps['cc']>(props.cc) expectType<ExpectedProps['cc']>(props.cc)
expectType<ExpectedProps['dd']>(props.dd) expectType<ExpectedProps['dd']>(props.dd)
expectType<ExpectedProps['ee']>(props.ee)
expectType<ExpectedProps['ff']>(props.ff)
expectType<ExpectedProps['ccc']>(props.ccc) expectType<ExpectedProps['ccc']>(props.ccc)
expectType<ExpectedProps['ddd']>(props.ddd) expectType<ExpectedProps['ddd']>(props.ddd)
expectType<ExpectedProps['eee']>(props.eee)
expectType<ExpectedProps['fff']>(props.fff)
// props should be readonly // props should be readonly
expectError((props.a = 1)) expectError((props.a = 1))
@ -88,11 +118,16 @@ describe('with object props', () => {
// should also expose declared props on `this` // should also expose declared props on `this`
expectType<ExpectedProps['a']>(this.a) expectType<ExpectedProps['a']>(this.a)
expectType<ExpectedProps['b']>(this.b) expectType<ExpectedProps['b']>(this.b)
expectType<ExpectedProps['e']>(this.e)
expectType<ExpectedProps['bb']>(this.bb) expectType<ExpectedProps['bb']>(this.bb)
expectType<ExpectedProps['cc']>(this.cc) expectType<ExpectedProps['cc']>(this.cc)
expectType<ExpectedProps['dd']>(this.dd) expectType<ExpectedProps['dd']>(this.dd)
expectType<ExpectedProps['ee']>(this.ee)
expectType<ExpectedProps['ff']>(this.ff)
expectType<ExpectedProps['ccc']>(this.ccc) expectType<ExpectedProps['ccc']>(this.ccc)
expectType<ExpectedProps['ddd']>(this.ddd) expectType<ExpectedProps['ddd']>(this.ddd)
expectType<ExpectedProps['eee']>(this.eee)
expectType<ExpectedProps['fff']>(this.fff)
// props on `this` should be readonly // props on `this` should be readonly
expectError((this.a = 1)) expectError((this.a = 1))
@ -115,10 +150,14 @@ describe('with object props', () => {
a={1} a={1}
b="b" b="b"
bb="bb" bb="bb"
e={() => {}}
cc={['cc']} cc={['cc']}
dd={['dd']} dd={['dd']}
ee={() => 'ee'}
ccc={['ccc']} ccc={['ccc']}
ddd={['ddd']} ddd={['ddd']}
eee={() => ({ a: 'eee' })}
fff={(a, b) => ({ a: a > +b })}
// should allow extraneous as attrs // should allow extraneous as attrs
class="bar" class="bar"
// should allow key // should allow key