TypeScript联合类型调用setValues出现never类型错误如何解决?
TypeScript联合类型调用方法时参数类型为never的解决办法
问题场景
定义了以下类和类型:
class FirstClass { values: FirstValuesType = {} as FirstValuesType; setValues(values: FirstValuesType): void { this.values = { ...values }; } } class SecondClass { values: SecondValuesType = {} as SecondValuesType; setValues(values: SecondValuesType): void { this.values = { ...values }; } } interface CommonValuesType { id: number; property1: string; property2: string; } enum FirstReasonEnum { A, B, C } enum SecondReasonEnum { X, Y, Z } interface FirstValuesType extends CommonValuesType { reason: FirstReasonEnum; } interface SecondValuesType extends CommonValuesType { reason: SecondReasonEnum; }
当声明联合类型变量并调用setValues时:
const model: FirstClass | SecondClass; model.setValues(newValues);
会出现TypeScript错误:
Argument of type '{ id: number; property1: string; property2: string; reason: FirstReasonEnum; }' is not assignable to parameter of type 'never'.
The intersection 'FirstValuesType & SecondValuesType' was reduced to 'never' because property 'reason' has conflicting types in some constituents.(2345)
原因是:TypeScript对联合类型的方法参数会取类型交集,而FirstValuesType和SecondValuesType的reason字段是互斥枚举,交集为never,导致无法传入任何有效值。
解决方法
1. 使用类型守卫(Type Guard)
通过instanceof明确model的具体类型,再调用对应方法:
const newValuesFirst: FirstValuesType = { id: 1, property1: "a", property2: "b", reason: FirstReasonEnum.A }; const newValuesSecond: SecondValuesType = { id: 2, property1: "c", property2: "d", reason: SecondReasonEnum.X }; // 用instanceof判断类型 if (model instanceof FirstClass) { model.setValues(newValuesFirst); } else { model.setValues(newValuesSecond); }
2. 给类添加可辨识属性
在类中新增唯一标识字段,让TypeScript能自动区分联合类型:
// 修改类定义,添加可辨识属性 class FirstClass { type: "first" = "first"; values: FirstValuesType = {} as FirstValuesType; setValues(values: FirstValuesType): void { this.values = { ...values }; } } class SecondClass { type: "second" = "second"; values: SecondValuesType = {} as SecondValuesType; setValues(values: SecondValuesType): void { this.values = { ...values }; } } // 调用时通过type字段判断 if (model.type === "first") { model.setValues(newValuesFirst); } else { model.setValues(newValuesSecond); }
3. 泛型基类抽象逻辑
用泛基类封装共同方法,减少重复代码,同时保持类型安全:
abstract class BaseClass<T extends CommonValuesType> { values: T = {} as T; setValues(values: T): void { this.values = { ...values }; } } // 继承泛型基类 class FirstClass extends BaseClass<FirstValuesType> {} class SecondClass extends BaseClass<SecondValuesType> {} // 若仍需联合类型,搭配类型守卫使用即可
4. 类型断言(不推荐)
如果能100%确定model的具体类型,可以用断言绕过检查,但会丢失类型安全:
(model as FirstClass).setValues(newValuesFirst);
内容的提问来源于stack exchange,提问作者Renaud is Not Bill Gates
相关产品推荐
相关产品推荐

