TypeScript泛型条件类型继承联合类型时的类型推断失败问题
TypeScript泛型条件类型的类型推断问题
定义了ItemErrors条件类型,用于生成与输入类型结构一致的错误类型(属性为可选的错误信息):
// 自定义条件类型 type ItemErrors<IT> = { [P in keyof IT]?: IT[P] extends object ? ItemErrors<IT[P]> : IT[P] extends any[] ? string[] : string };
存在两个都包含name属性的类型:
type WithName = { name: string other: number obj: { inner: boolean } } type AlsoWithName = { name: string cool: boolean }
它们的联合类型UnionHasName可以确定必然包含name属性:
type UnionHasName = WithName | AlsoWithName
用于测试的打印函数:
function prints(mustbestring: string){ console.log(mustbestring) }
以下几个函数都能正常完成类型推断:
works:直接接收UnionHasName类型参数,my.name被正确推断为stringalsoWorks:泛型函数,T继承UnionHasName,something.name被正确推断为stringstillWorks:接收ItemErrors<WithName>类型参数,something.name被推断为string | undefined,配合?? ""能满足prints的参数要求evenStillWorks:接收ItemErrors<UnionHasName>类型参数,something.name同样被推断为string | undefined,可正常调用prints
但下面的泛型函数doesNotWork中,类型推断失败:
function doesNotWork<T extends UnionHasName>(something: ItemErrors<T>){ // 此处报错:类型“ItemErrors<T>["name"]”的参数不能赋给类型“string”的参数 prints(something.name ?? "") }
问题原因分析
TypeScript处理泛型条件类型时,对于未具体化的泛型类型参数(也就是T只是一个受约束的泛型,而非具体类型),无法完全展开和解析条件类型的最终结果。
虽然T extends UnionHasName确保了T一定有name: string属性,但ItemErrors<T>是一个条件类型,TypeScript在编译时没法确定:当T是任意符合约束的类型时,ItemErrors<T>["name"]的具体类型——它只能将其推断为一个条件类型的引用,而非解析后的string | undefined。
对比来看:
ItemErrors<WithName>或ItemErrors<UnionHasName>是具体类型,TypeScript可以直接展开条件类型得到明确结构- 泛型函数
alsoWorks中直接访问T的name属性,因为T的约束明确了name是string,不需要解析条件类型,推断自然成功
如果要解决这个问题,可以通过约束ItemErrors<T>的name属性类型帮助TypeScript完成推断,比如添加额外的类型约束:
function doesNotWork<T extends UnionHasName>(something: ItemErrors<T> & { name?: string }){ prints(something.name ?? "") }
内容的提问来源于stack exchange,提问作者pooley1994
相关产品推荐
相关产品推荐

