扩展类的类型

时间:2019-05-06 13:48:32

标签: typescript

我想输入一个变量,例如其值必须是扩展基类的类的名称。

class Base {}
class Foo extends Base {}
class Bar extends Base {}

function myFunction(myObject: Base) {
  let objectTypeAsString: string = foo.constructor.name;
}

let foo = new Foo();

myFunction(foo);

此代码有效,但是 objectTypeAsString 键入为 string ,我想使用一种更安全的类型。 我知道 foo.constructor.name 是在运行时获取的,但是也许有一种更聪明的方法来定义和获取类名。

1 个答案:

答案 0 :(得分:1)

注意:我将向空类添加属性以避免weirdness


这实际上是不可能的,并且解决方法可能比他们值得的麻烦更多。 known issue是类实例的constructor属性未在TypeScript中强类型化。构造函数的name属性也只是键入为string。因此,您必须尝试手动执行这些操作,这很麻烦且无法扩展...

...并且编译器动不动就动弹。您显然不能手动强地键入类的静态方面的name属性:

class Hmm {
  hmm = 123; 
  static readonly name: "Hmm"; // error!
  //              ~~~~
  // Static property 'name' conflicts with built-in property 
  // 'Function.name' of constructor function 'Hmm'.
}

即使您可以做到这一点,当您开始扩展类时,也会使编译器非常生气:

class Hmm {
  hmm = 123;
  //@ts-ignore
  static readonly name: "Hmm";
}

class Oops extends Hmm // error!
//    ~~~~
// Class static side 'typeof Oops' incorrectly 
// extends base class static side 'typeof Hmm'.
{
  oops = 456;
  //@ts-ignore
  static readonly name: "Oops";
}

因为子类需要可分配给超类,但是"Oops"不可分配给"Hmm"。这意味着子类将不必严格地是子类,而我们将需要类似generics的子类。但是您不能在静态属性中使用实例泛型类型参数,因此我们必须忘记类的静态方面。


我们可以做的一件事就是使用trick强烈地自己键入constructor实例属性,这将在TS3.5中获得更多tricky

// this is now generic
class Base<N extends string = "Base"> {
  ["constructor"]: typeof Base & { name: N }; // strongly type "constructor"
  base = "b"; 
}
class Foo extends Base<"Foo"> {
  foo = "f";
}
class Bar extends Base<"Bar"> {
  bar = "b";
}

// this is now generic too
function myFunction<N extends string>(myObject: Base<N>): N {
  return myObject.constructor.name;
}

let foo = new Foo();

myFunction(foo); // "Foo"

一切都可行,但是很丑。因此,我想简短的答案应该是“您不能做到这一点”,而稍长一点的答案应该是“您可以稍微做到这一点但您不应该这样做”。

哦,希望对您有所帮助。祝你好运!