Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 2 commits into from
Apr 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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