Typescript可以推断通过其基类方法实例化的扩展类实例的类型吗? [英] Can Typescript infer the type of an instance of an extension class instantiated by a method of its base?

查看:145
本文介绍了Typescript可以推断通过其基类方法实例化的扩展类实例的类型吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请考虑以下Typescript代码段:

Consider the following Typescript snippet:

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

Animals can have babies, and a baby should be the same kind of animal as the parent, i.e., should be an instance of the same class as the parent. How do I assign types in this situation, so that Typescript knows that sorachiJr: Cat?

上面的代码段无效。返回新this.constructor(name)会产生错误 [ts]无法使用' ,其类型缺少调用或构造签名。在VS Code中。我能够找到并理解的唯一解决方案是将 this.constructor(name)替换为(< any> this.constructor)(name) (< any> this).constructor(name),但随后为 sorachiJr 也是任何,而不是 Cat 。我尝试强制转换为此类型的,而不是任何,但收到错误 [ts]无法找到名字 this。

The code snippet above doesn't work. The line return new this.constructor(name) produces the error [ts] Cannot use 'new' with an expression whose type lacks a call or construct signature. in VS Code. The only solution I was able to find and understand was replacing this.constructor(name) with (<any>this.constructor)(name) or (<any>this).constructor(name), but then the type inferred for sorachiJr is any, too, rather than Cat. I tried casting to typeof this rather than any, but got the error [ts] Cannot find name 'this'.

我如何说服打字稿说生婴儿是物种保护活动?

How can I convince Typescript that having babies is a species-preserving operation?

推荐答案

保存调用该方法的类的类型很容易,我们只使用多态的 this 类型。为了使ts确信 constructor 将是一个接受 string 并返回与当前实例类型相同的实例的构造函数。类需要类型断言

The preserving the type of the class the method was called on is easy, we just use the polymorphic this type. To convince the ts that constructor will be a constructor that takes a string and returns an instance the same type as the current class requires a type assertion

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 参数,它可能需要更多或更少的参数。这使该构造函数的类型不安全。

Note Typescript can't validate the fact that the derived class constructor only expects a single string parameter, it might require more or less parameters. This makes this constructor not type safe.

这篇关于Typescript可以推断通过其基类方法实例化的扩展类实例的类型吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆