Skip to content

Commit 026eb72

Browse files
authored
fix(types): allow use PropType with Function (#915)
close #748
1 parent 4b03b92 commit 026eb72

File tree

2 files changed

+47
-1
lines changed

2 files changed

+47
-1
lines changed

packages/runtime-core/src/componentProps.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,14 @@ interface PropOptions<T = any> {
3939

4040
export type PropType<T> = PropConstructor<T> | PropConstructor<T>[]
4141

42-
type PropConstructor<T = any> = { new (...args: any[]): T & object } | { (): T }
42+
type PropConstructor<T = any> =
43+
| { new (...args: any[]): T & object }
44+
| { (): T }
45+
| PropMethod<T>
46+
47+
type PropMethod<T> = T extends (...args: any) => any // if is function with args
48+
? { new (): T; (): T; readonly proptotype: Function } // Create Function like contructor
49+
: never
4350

4451
type RequiredKeys<T, MakeDefaultRequired> = {
4552
[K in keyof T]: T[K] extends

test-dts/defineComponent.test-d.tsx

+39
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,16 @@ describe('with object props', () => {
1212
interface ExpectedProps {
1313
a?: number | undefined
1414
b: string
15+
e?: Function
1516
bb: string
1617
cc?: string[] | undefined
1718
dd: string[]
19+
ee?: () => string
20+
ff?: (a: number, b: string) => { a: boolean }
1821
ccc?: string[] | undefined
1922
ddd: string[]
23+
eee: () => { a: string }
24+
fff: (a: number, b: string) => { a: boolean }
2025
}
2126

2227
type GT = string & { __brand: unknown }
@@ -29,6 +34,7 @@ describe('with object props', () => {
2934
type: String,
3035
required: true
3136
},
37+
e: Function,
3238
// default value should infer type and make it non-void
3339
bb: {
3440
default: 'hello'
@@ -40,23 +46,42 @@ describe('with object props', () => {
4046
type: Array as PropType<string[]>,
4147
required: true
4248
},
49+
// return type
50+
ee: Function as PropType<() => string>,
51+
// arguments + object return
52+
ff: Function as PropType<(a: number, b: string) => { a: boolean }>,
4353
// explicit type casting with constructor
4454
ccc: Array as () => string[],
4555
// required + contructor type casting
4656
ddd: {
4757
type: Array as () => string[],
4858
required: true
59+
},
60+
// required + object return
61+
eee: {
62+
type: Function as PropType<() => { a: string }>,
63+
required: true
64+
},
65+
// required + arguments + object return
66+
fff: {
67+
type: Function as PropType<(a: number, b: string) => { a: boolean }>,
68+
required: true
4969
}
5070
},
5171
setup(props) {
5272
// type assertion. See https://github.com/SamVerschueren/tsd
5373
expectType<ExpectedProps['a']>(props.a)
5474
expectType<ExpectedProps['b']>(props.b)
75+
expectType<ExpectedProps['e']>(props.e)
5576
expectType<ExpectedProps['bb']>(props.bb)
5677
expectType<ExpectedProps['cc']>(props.cc)
5778
expectType<ExpectedProps['dd']>(props.dd)
79+
expectType<ExpectedProps['ee']>(props.ee)
80+
expectType<ExpectedProps['ff']>(props.ff)
5881
expectType<ExpectedProps['ccc']>(props.ccc)
5982
expectType<ExpectedProps['ddd']>(props.ddd)
83+
expectType<ExpectedProps['eee']>(props.eee)
84+
expectType<ExpectedProps['fff']>(props.fff)
6085

6186
// props should be readonly
6287
expectError((props.a = 1))
@@ -76,23 +101,33 @@ describe('with object props', () => {
76101
const props = this.$props
77102
expectType<ExpectedProps['a']>(props.a)
78103
expectType<ExpectedProps['b']>(props.b)
104+
expectType<ExpectedProps['e']>(props.e)
79105
expectType<ExpectedProps['bb']>(props.bb)
80106
expectType<ExpectedProps['cc']>(props.cc)
81107
expectType<ExpectedProps['dd']>(props.dd)
108+
expectType<ExpectedProps['ee']>(props.ee)
109+
expectType<ExpectedProps['ff']>(props.ff)
82110
expectType<ExpectedProps['ccc']>(props.ccc)
83111
expectType<ExpectedProps['ddd']>(props.ddd)
112+
expectType<ExpectedProps['eee']>(props.eee)
113+
expectType<ExpectedProps['fff']>(props.fff)
84114

85115
// props should be readonly
86116
expectError((props.a = 1))
87117

88118
// should also expose declared props on `this`
89119
expectType<ExpectedProps['a']>(this.a)
90120
expectType<ExpectedProps['b']>(this.b)
121+
expectType<ExpectedProps['e']>(this.e)
91122
expectType<ExpectedProps['bb']>(this.bb)
92123
expectType<ExpectedProps['cc']>(this.cc)
93124
expectType<ExpectedProps['dd']>(this.dd)
125+
expectType<ExpectedProps['ee']>(this.ee)
126+
expectType<ExpectedProps['ff']>(this.ff)
94127
expectType<ExpectedProps['ccc']>(this.ccc)
95128
expectType<ExpectedProps['ddd']>(this.ddd)
129+
expectType<ExpectedProps['eee']>(this.eee)
130+
expectType<ExpectedProps['fff']>(this.fff)
96131

97132
// props on `this` should be readonly
98133
expectError((this.a = 1))
@@ -115,10 +150,14 @@ describe('with object props', () => {
115150
a={1}
116151
b="b"
117152
bb="bb"
153+
e={() => {}}
118154
cc={['cc']}
119155
dd={['dd']}
156+
ee={() => 'ee'}
120157
ccc={['ccc']}
121158
ddd={['ddd']}
159+
eee={() => ({ a: 'eee' })}
160+
fff={(a, b) => ({ a: a > +b })}
122161
// should allow extraneous as attrs
123162
class="bar"
124163
// should allow key

0 commit comments

Comments
 (0)