Skip to content

Commit

Permalink
fix(types): allow use PropType with Function (#915)
Browse files Browse the repository at this point in the history
close #748
  • Loading branch information
pikax authored Apr 3, 2020
1 parent 4b03b92 commit 026eb72
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 1 deletion.
9 changes: 8 additions & 1 deletion packages/runtime-core/src/componentProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
39 changes: 39 additions & 0 deletions test-dts/defineComponent.test-d.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand All @@ -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'
Expand All @@ -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))
Expand All @@ -76,23 +101,33 @@ 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))

// 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))
Expand All @@ -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
Expand Down

0 comments on commit 026eb72

Please sign in to comment.