TypeScript条件扩展数组或对象不符合预期,求原因解析
为什么你的TypeScript泛型会抛出“Type 'id' cannot be used to index type 'T'”错误
错误核心原因
你遇到的问题本质是TypeScript泛型条件类型的检查机制限制:当你为泛型参数T设定{ id: unknown } | Array<{ id: unknown }>的联合约束后,条件分支中的代码会被针对整个约束范围做有效性校验,而非仅针对分支对应的子类型。
具体来说,在else分支中,你逻辑上认为T必然是带id属性的对象,但TypeScript不会因为T extends Array<any>的判断就自动将T的约束窄化为{ id: unknown }。它仍然会考虑T可能是数组类型(毕竟约束允许数组),而数组本身并没有id属性,因此T["id"]会被判定为无效索引。
哪怕从逻辑推导上,非数组的T必然符合{ id: unknown },但TypeScript的泛型检查不会在条件分支中对泛型参数的约束做“窄化”推导——它只会确保每个分支的代码对所有符合原始约束的T都具备语法合法性,而数组类型显然不支持id索引。
附带逻辑修正:数组分支的错误
你的数组分支还存在一个逻辑错误:Omit<T, "id">是对数组类型本身做操作,但你真正需要的是对数组元素类型去除id属性。应该改为Omit<T[number], "id">,其中T[number]表示数组元素的类型。
修正后的完整类型(验证逻辑)
虽然你提到已经知道用双层extend可解决问题,这里给出同时修复数组分支错误的版本:
type APIDataShape<T extends { id: unknown } | Array<{ id: unknown }>> = T extends Array<any> ? Array<{ id: T[number]["id"]; attributes: Omit<T[number], "id">; }> : T extends { id: unknown } ? { id: T["id"]; attributes: Omit<T, "id">; } : never;
通过嵌套的T extends { id: unknown }检查,明确告知TypeScript当前分支的T具备id属性,从而消除错误。
内容的提问来源于stack exchange,提问作者MTG
相关产品推荐
相关产品推荐

