我们可以用TypeScrip编写自己的方法来扩展已知的类型class A.扩展后,新类型的实例将具有正确的类型,并且可以通过类型系统访问字段ae:

class A {
  a = "a";
}

function extend(originalType: typeof A){
  return class extends originalType {
    e = "e"
  }
}

const ExtA = extend(A);
const extA = new ExtA();
console.log(extA.a, extA.e); // both .a and .e are accessible.

如果我们try 使用相同的函数声明来扩展子类class B,显然,字段b在类型系统中将不可用:

// continued...
class B extends A {
  b = "b";
}

const ExtB = extend(B);
const extB = new ExtB();
console.log(extB.a, extB.b, extB.e); // Property 'b' does not exist on type '(Anonymous class)'

这是TSplayground link

我曾try 编写一个extend2extend3方法,可以在A的任何子类上工作,但没有成功.

这是两次try ,使用泛型,都会导致TS编译错误:

// A mixin class must have a constructor with a single rest parameter of type 'any[]'.
function extend2<T extends typeof A>(subclassType: T) {
    return class extends subclassType {
    e = "e"
  }
}

// Class '(Anonymous class)' incorrectly extends base class 'T'.
  '(Anonymous class)' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'A'
function extend3<T extends A>(subclassType: new (...args: any[]) => T) {
      return class extends subclassType {
    e = "e"
  }
}

在这一点上,有没有办法在TypeScrip(5.3.3版)中实现这一点?

推荐答案

您可以通过将extend设置为泛型来实现这一点,就像对extend2所做的那样:

function extend<ClassType extends typeof A>(originalType: ClassType) {
  return class extends originalType {
    e = "e";
  };
}

...但正如您所发现的,just这样做会在return class extends...语句中产生以下错误:

MixIn类必须有一个构造函数,该构造函数具有类型为‘any[]’的单个REST参数

要解决这个问题,给A一个构造函数,其中只有一个类型为any[]的REST参数:

class A {
  constructor(...args: any[]) {} // <== Needed for `extend` above
  a = "a";
}

有了这些更改,您的示例就可以工作了.

Playground link

Typescript相关问答推荐

如何使用Generics保留构造函数的类型信息?

如果我有对象的Typescript类型,如何使用其值的类型?

typescript抱怨值可以是未定义的,尽管类型没有定义

有没有一种方法可以在保持类型的可选状态的同时更改类型?

未在DIST中正确编译TypeScrip src模块导入

如何判断对象是否有重叠的叶子并产生有用的错误消息

在实现自定义主题后,Angular 不会更新视图

使用2个泛型类型参数透明地处理函数中的联合类型

TypeScrip省略了类型参数,仅当传递另一个前面的类型参数时才采用默认类型

如何在Typescript 中组合unions ?

转换器不需要的类型交集

打字错误推断

将超类型断言为类型脚本中的泛型参数

类型脚本中参数为`T`和`t|unfined`的重载函数

如何创建一个将嵌套类属性的点表示法生成为字符串文字的类型?

如何将元素推入对象中的类型化数组

如何让Record中的每个值都有独立的类型?

为什么 typescript 在对象合并期间无法判断无效键?

基于泛型的柯里化函数的条件参数

类型string不可分配给类型string| 联盟| 的'