Invalid/incomplete type inferred by generic components
Vue version
3.3.8
Link to minimal reproduction
Steps to reproduce
I have a generic component, with a property mapping straight to the generic type:
<script setup lang="ts" generic="T">
import type { PropType } from 'vue'
const props = defineProps({
test: {
type: Object as PropType<T>,
required: true,
default: undefined,
},
})
</script>
The type inferred by props.test
is not fully resolved, and instead of being T
, it becomes the following:
[{
type: PropType<T>;
required: true;
}] extends [Prop<infer V, infer D>] ? unknown extends V ? IfAny<V, V, D> : V : {
type: PropType<T>;
required: true;
}
What is expected?
The type of the property should be resolved correctly to the generic type.
What is actually happening?
I narrowed this down to the InferPropType<T>
type around here: https://github.com/vuejs/core/blob/83e618f316d367b43586646be285a41fd8a30c78/packages/runtime-core/src/componentProps.ts#L125-L128
Adding an extra condition to narrow inference even further makes the type work correctly:
type InferPropType<T> = [T] extends [null]
? any // null & true would fail to infer
: [T] extends [{ type: null | true }]
? any // As TS issue https://github.com/Microsoft/TypeScript/issues/14829 // somehow `ObjectConstructor` when inferred from { (): T } becomes `any` // `BooleanConstructor` when inferred from PropConstructor(with PropMethod) becomes `Boolean`
: [T] extends [ObjectConstructor | { type: ObjectConstructor }]
? Record<string, any>
: [T] extends [BooleanConstructor | { type: BooleanConstructor }]
? boolean
: [T] extends [DateConstructor | { type: DateConstructor }]
? Date
: [T] extends [(infer U)[] | { type: (infer U)[] }]
? U extends DateConstructor
? Date | InferPropType<U>
: InferPropType<U>
// ~~~~~~~~ extra condition below, specific for `PropOptions`
: [T] extends [PropOptions<infer V, infer D>]
? unknown extends D
? V
: V | D :
// ~~~~~~~~
: [T] extends [Prop<infer V, infer D>]
? unknown extends V
? IfAny<V, V, D>
: V
: T
System Info
No response
Any additional comments?
No response
A potential workaround is to use the (experimental) defineModel(...)
macro. Typings for that are actually OK!