Typescript泛型推断为何未识别rec与rec2类型不一致?
问题原因
你的写法里createMyType的泛型约束是T extends MyType<Record<string, any>>,TypeScript在做类型推断时,会自动推导满足约束的最宽松的公共超类型:
- 第一个示例中,
rec的类型是{idFoo: number},rec2是number,二者的公共超类型不满足Record<string, any>的要求,所以直接报错,符合预期。 - 第二个示例中,
{idFoo: number}和空对象{}的公共超类型正好是Record<string, any>,TypeScript会直接把MyType的泛型参数TRecord推导为Record<string, any>,此时两个属性都符合类型要求,自然不会抛出错误。
你原来的写法没有让TypeScript优先锁定TRecord的具体类型,而是允许它自动放宽到满足约束的公共超类型,所以才会出现第二个示例不报错的问题。
正确写法
你只需要把createMyType的泛型参数调整为直接对应TRecord,让TypeScript优先从入参里推导TRecord的具体类型,而不是先推导整个MyType实例的类型即可:
type MyType<TRecord extends Record<string,any>> = { rec: TRecord rec2: TRecord } const myRec = { idFoo: 3 } // 泛型参数直接对应TRecord function createMyType<TRecord extends Record<string, any>>(obj: MyType<TRecord>): MyType<TRecord> { return obj } const myType = createMyType({ rec: myRec, rec2: 3, // 依然报错 }) const myType2 = createMyType({ rec: myRec, rec2: {}, // 现在会正常报错:类型 "{}" 中缺少属性 "idFoo",但类型 "{ idFoo: number; }" 中需要该属性 })
如果你的TS版本在5.4以上,还可以配合NoInfer工具类型强制让TS只从rec属性推导TRecord,避免出现双向推导放宽类型的情况,写法更严谨:
function createMyType<TRecord extends Record<string, any>>(obj: { rec: TRecord, rec2: NoInfer<TRecord> }): MyType<TRecord> { return obj }
内容的提问来源于stack exchange,提问作者sam256
相关产品推荐
相关产品推荐

