考虑以下Typescript代码段:
class Animal {
constructor(name: string) {
this.name = name;
}
name: string;
haveBaby(name: string): ?? return type ?? {
return new this.constructor(name); // Error
}
}
class Cat extends Animal {}
class Dog extends Animal {}
class Gerbil extends Animal {} // etc.
let sorachi = new Cat("Sorachi"); // a: Cat
let sorachiJr = a.haveBaby("Sorachi Jr."); // I want: sorachiJr: Cat
动物可以有婴儿,并且婴儿应与父母具有相同种类的动物,即应与父母属于同一类的实例。在这种情况下如何分配类型,以便Typescript知道sorachiJr: Cat
?
上面的代码段无效。在VS Code中,行return new this.constructor(name)
产生错误[ts] Cannot use 'new' with an expression whose type lacks a call or construct signature.
。我能够找到并理解的唯一解决方案是将this.constructor(name)
替换为(<any>this.constructor)(name)
或(<any>this).constructor(name)
,但是为sorachiJr
推断的类型也是any
,而不是Cat
。我尝试强制转换为typeof this
而不是any
,但收到错误[ts] Cannot find name 'this'
。
我如何说服Typescript相信婴儿是一种保护物种的活动?
答案 0 :(得分:3)
保存调用该方法的类的类型很容易,我们只使用多态this
类型。为了使ts确信constructor
将是一个接受string
并返回与当前类相同类型的实例的构造函数,需要类型声明
type AnimalConstructor<T extends Animal> = new (name: string) => T
class Animal {
constructor(name: string) {
this.name = name;
}
name: string;
haveBaby(name: string): this {
return new (this.constructor as AnimalConstructor<this>)(name);
}
}
class Cat extends Animal {}
class Dog extends Animal {}
class Gerbil extends Animal {} // etc.
let sorachi = new Cat("Sorachi"); // a: Cat
let sorachiJr = sorachi.haveBaby("Sorachi Jr.");
注意:Typescript无法验证派生类构造函数仅需要单个string
参数这一事实,它可能需要更多或更少的参数。这使该构造函数的类型不安全。