继承类时省略属性

9

我正在尝试派生一个类,将一个在基类中被定义为必需的字段设置为可选。

例如:

class Base {
  param1! : string;
  param2! : string;
}

class Derived extends Omit<Base, "param1">{
} 

这会导致错误ts(2693):

'Omit'仅适用于类型,但它在这里被用作值。

如果这是一个XY问题,我的真正解决方案是:

  1. 我生成的类在每次构建时都会被重新生成(因此我无法手动修改它们,或者在生成时进行一些修改)
  2. 生成的类将所有属性定义为必需的(类似于上面的Base)。
  3. 我需要向某些生成的方法和属性添加装饰器。
  4. 我需要允许Base类的Partial实例。(理想情况下只添加一次装饰器)。

理想情况下,我想使用RequiredOmitPickPartial来扩展Base类,以便派生出多个省略/要求正确属性的类。

我已经几乎放弃了所有这些脚手架/模板代码,想要手动编写模型/SQL/REST。

(我对TypeScript还很新)


1
你需要使用 implements 而不是 extends。因为 extends 用于扩展类,因此 TS 需要一个值,而你正在尝试使用 Omit。请参见示例 - captain-yossarian from Ukraine
抱歉耽搁了,这就是问题所在。谢谢!所以 Pick, Partial, Required, Omit 总是“返回”接口,无论给定的是类还是接口?如果您将其发布为答案,我会接受,因为它涵盖了问题的主要问题。但是,虽然装饰器的效果在派生类中仍然存在,但它们不会被“重新计算/重新应用”(即装饰器对可选类型和必需类型应该具有不同的影响)。有没有办法解决这个问题?我应该从问题中删除它并打开一个新问题吗?谢谢! - GCon
1个回答

7
TS有两个作用域(worlds)。第一个是用于运行时值的,第二个是用于类型的。根据JS规范和文档
引用:
extends”关键字可用于自定义类以及内置对象的子类化。
这意味着,在extends之后,TypeScript和JavaScript都期望运行时值。这就是为什么你会收到错误信息的原因,因为Omit是一个纯类型,它在编译过程中被擦除了。在这种情况下使用Omit等同于这个纯javascript:
class Derived extends {
}

这个语法是错误的。 相反,你需要使用implements。这个关键字来自类型范围,帮助TS验证类声明。
class Base {
  param1!: string;
  param2!: string;
}

class Derived implements Omit<Base, "param1">{
  param2!: string;
} 

关于装饰器,请提供一个最小可复现的例子。

3
这正是问题所在。此外,在nestjs中,有PickTypePartialTypeOmitTypemapped-types专门为此而设计。在底层,function PartialType<T>(classRef: Type<T>): Type<Partial<T>>允许从基类(通过扩展)继承,而不是通过实现修改后的基类接口来实现多态性。其中一些细节仍然不清楚,但这是正确的解决方案。谢谢! - GCon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接