TypeScript中交叉类型无法赋值给泛型类型的报错疑问
TypeScript 类型不匹配问题解析
先看这段代码:
type X = { a: number; b: number; }; const a = <T extends X>(t: T): T => { const { b, ...noB } = t; const r = { ...noB, b: 1 }; return r; };
这里noB的类型为Omit<T, "b">,r的类型为Omit<T, "b"> & { b: number },但TypeScript抛出了如下错误:
Type 'Omit<T, "b"> & { b: number; }' is not assignable to type 'T'. 'Omit<T, "b"> & { b: number; }' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'X'.ts(2322)
你觉得Omit<T, "b"> & { b: number }应该和T等价,但问题核心在于T可以是X的子类型,子类型可能对b有更严格的类型约束。
举个具体例子:
假设我们把T实例化为一个字面量类型:
const obj = { a: 3, b: 2 } as const; a(obj); // 此时T被推断为 { readonly a: 3; readonly b: 2; }
这时r的类型是{ readonly a: 3 } & { b: number },它的b是宽泛的number类型,但原T的b是具体的字面量类型2。number类型的值无法赋值给2类型的变量,所以TypeScript会报错。
简单来说,你把b硬改成了1(属于number类型),但T的b可能是number的子类型(比如2、0这类字面量),新的b类型和原T的b类型不再兼容。
解决思路
- 如果需要返回原类型T,要保持
b的类型与T一致:
const a = <T extends X>(t: T): T => { const { b, ...noB } = t; const r = { ...noB, b }; // 复用原b的值,保留原类型 return r; };
- 如果逻辑就是要把
b改成1,则调整返回类型,不要强行返回T:
const a = <T extends X>(t: T): Omit<T, "b"> & { b: number } => { const { b, ...noB } = t; const r = { ...noB, b: 1 }; return r; };
- 如果一定要返回T且修改
b的值,可以用类型断言(注意这会跳过类型检查,需确保逻辑安全):
const a = <T extends X>(t: T): T => { const { b, ...noB } = t; const r = { ...noB, b: 1 } as T; return r; };
内容的提问来源于stack exchange,提问作者Ricardo Baptista
相关产品推荐
相关产品推荐

