我想输入一个变量,例如其值必须是扩展基类的类的名称。
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 是在运行时获取的,但是也许有一种更聪明的方法来定义和获取类名。
答案 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"
一切都可行,但是很丑。因此,我想简短的答案应该是“您不能做到这一点”,而稍长一点的答案应该是“您可以稍微做到这一点但您不应该这样做”。
哦,希望对您有所帮助。祝你好运!