TypeScript类继承使用Omit工具类型报ts(2693)错误求解
问题复现
尝试通过继承+类型工具修改基类字段可选性时触发ts(2693)错误:
class Base { param1! : string; param2! : string; } class Derived extends Omit<Base, "param1">{ }
错误提示:
'Omit' only refers to a type, but is being used as a value here.
你的实际场景约束:
- 项目所用类为构建时自动生成,无法手动修改生成的类,也无法在生成流程中加入自定义逻辑
- 自动生成的类所有属性均为必填
- 需要为部分自动生成的方法、属性添加装饰器
- 需要支持创建Base类的Partial实例,且装饰器仅需添加一次
问题根因
extends 关键字后必须传入可在运行时访问的类构造函数值,而Omit、Partial、Pick、Required都属于TypeScript的类型工具,仅在编译阶段的类型检查环节生效,编译为JS后会被完全擦除,没有对应的运行时实体,因此直接extends Omit<Base, "param1">会触发上述错误。
适配场景的最优方案
利用TypeScript的声明合并特性,在不修改自动生成基类、不改动生成流程的前提下,同时满足装饰器复用、灵活配置字段必填性的需求:
- 先编写运行时类,直接继承自动生成的
Base类,所有需要添加的装饰器统一在这个类上声明,仅需编写一次 - 声明同名接口,通过类型工具修改字段的可选/必填规则,TS会自动把接口定义的类型合并到同名类上,不会产生任何额外运行时代码
示例代码:
// 提前定义通用类型工具,支持灵活指定哪些字段设为可选 type SetOptional<T, Keys extends keyof T> = Omit<T, Keys> & Partial<Pick<T, Keys>>; // 运行时类:继承基类,统一添加装饰器 class CustomBase extends Base { // 在这里给需要的属性、方法加装饰器即可,所有实例都会生效 // 例如 @Column()、@ApiModelProperty() 这类装饰器直接写在这里 } // 同名接口:合并自定义类型规则,这里示例把param1设为可选 interface CustomBase extends SetOptional<Base, "param1"> {} // 按需派生其他规则的类,不需要重复加装饰器 class AllOptionalBase extends CustomBase {} interface AllOptionalBase extends Partial<Base> {} // 校验效果 const a = new CustomBase(); a.param2 = "test"; // param1为可选,缺省不会报类型错误 const b = new AllOptionalBase(); // 所有字段都可选,创建空实例也不报错
方案优势
- 完全不触碰自动生成的基类代码,也不需要修改构建生成流程,符合场景约束
- 装饰器仅需在
CustomBase上声明一次,所有派生类都能继承装饰器逻辑,不需要重复编写 - 类型规则灵活可组合,配合
SetOptional、SetRequired、Omit、Pick等工具,可以派生任意字段必填/可选规则的适配类 - 完整保留基类的原型链和运行时方法,不会破坏自动生成类自带的SQL、REST接口相关逻辑
不推荐的替代方案
如果只是需要做纯对象的类型校验,不需要类的运行时能力、不需要挂载装饰器,可以直接用类型别名定义结构,但这种方式没有对应的运行时类,无法满足加装饰器、调用类方法的需求:
type PartialBase = Partial<Base>; const tempObj: PartialBase = { param1: "demo" }; // 仅做类型校验,无运行时类能力
注意事项
如果你的项目开启了useDefineForClassFields(新版TS脚手架默认开启),不要在子类中通过重新声明字段的方式修改可选性,否则会覆盖基类的字段初始化逻辑,用上述接口合并的方式可以完全规避这个问题。
内容的提问来源于stack exchange,提问作者GCon
相关产品推荐
相关产品推荐

