Skip to content

Commit 9d36c61

Browse files
authored
types(runtime-core): improve PropType inference precision (vuejs#1863)
1 parent 4d51be7 commit 9d36c61

File tree

2 files changed

+18
-4
lines changed

2 files changed

+18
-4
lines changed

packages/runtime-core/src/componentProps.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,14 @@ export type ComponentObjectPropsOptions<P = Data> = {
4040
[K in keyof P]: Prop<P[K]> | null
4141
}
4242

43-
export type Prop<T> = PropOptions<T> | PropType<T>
43+
export type Prop<T, D = T> = PropOptions<T, D> | PropType<T>
4444

4545
type DefaultFactory<T> = () => T | null | undefined
4646

47-
interface PropOptions<T = any> {
47+
interface PropOptions<T = any, D = T> {
4848
type?: PropType<T> | true | null
4949
required?: boolean
50-
default?: T | DefaultFactory<T> | null | undefined
50+
default?: D | DefaultFactory<D> | null | undefined
5151
validator?(value: unknown): boolean
5252
}
5353

@@ -83,7 +83,7 @@ type InferPropType<T> = T extends null
8383
? Record<string, any>
8484
: T extends BooleanConstructor | { type: BooleanConstructor }
8585
? boolean
86-
: T extends Prop<infer V> ? V : T
86+
: T extends Prop<infer V, infer D> ? (unknown extends V ? D : V) : T
8787

8888
export type ExtractPropTypes<
8989
O,

test-dts/defineComponent.test-d.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ describe('with object props', () => {
2727
eee: () => { a: string }
2828
fff: (a: number, b: string) => { a: boolean }
2929
hhh: boolean
30+
ggg: 'foo' | 'bar'
3031
validated?: string
3132
}
3233

@@ -77,6 +78,11 @@ describe('with object props', () => {
7778
type: Boolean,
7879
required: true
7980
},
81+
// default + type casting
82+
ggg: {
83+
type: String as PropType<'foo' | 'bar'>,
84+
default: 'foo'
85+
},
8086
validated: {
8187
type: String,
8288
validator: (val: unknown) => val !== ''
@@ -97,6 +103,7 @@ describe('with object props', () => {
97103
expectType<ExpectedProps['eee']>(props.eee)
98104
expectType<ExpectedProps['fff']>(props.fff)
99105
expectType<ExpectedProps['hhh']>(props.hhh)
106+
expectType<ExpectedProps['ggg']>(props.ggg)
100107
expectType<ExpectedProps['validated']>(props.validated)
101108

102109
// @ts-expect-error props should be readonly
@@ -128,6 +135,7 @@ describe('with object props', () => {
128135
expectType<ExpectedProps['eee']>(props.eee)
129136
expectType<ExpectedProps['fff']>(props.fff)
130137
expectType<ExpectedProps['hhh']>(props.hhh)
138+
expectType<ExpectedProps['ggg']>(props.ggg)
131139

132140
// @ts-expect-error props should be readonly
133141
expectError((props.a = 1))
@@ -146,6 +154,7 @@ describe('with object props', () => {
146154
expectType<ExpectedProps['eee']>(this.eee)
147155
expectType<ExpectedProps['fff']>(this.fff)
148156
expectType<ExpectedProps['hhh']>(this.hhh)
157+
expectType<ExpectedProps['ggg']>(this.ggg)
149158

150159
// @ts-expect-error props on `this` should be readonly
151160
expectError((this.a = 1))
@@ -177,6 +186,7 @@ describe('with object props', () => {
177186
eee={() => ({ a: 'eee' })}
178187
fff={(a, b) => ({ a: a > +b })}
179188
hhh={false}
189+
ggg="foo"
180190
// should allow class/style as attrs
181191
class="bar"
182192
style={{ color: 'red' }}
@@ -194,6 +204,10 @@ describe('with object props', () => {
194204
// @ts-expect-error wrong prop types
195205
<MyComponent a={'wrong type'} b="foo" dd={{ n: 1 }} ddd={['foo']} />
196206
)
207+
expectError(
208+
// @ts-expect-error wrong prop types
209+
<MyComponent ggg="baz" />
210+
)
197211
// @ts-expect-error
198212
expectError(<MyComponent b="foo" dd={{ n: 'string' }} ddd={['foo']} />)
199213
})

0 commit comments

Comments
 (0)