TypeScript:继承类中静态方法的自引用返回类型

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/34098023/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 03:09:03  来源:igfitidea点击:

TypeScript: self-referencing return type for static methods in inheriting classes

genericsinheritancestatictypescriptself-reference

提问by Merott

With Polymorphic thisin TypeScript 1.7, as I discovered here, we can define a method in a class with a return type of this, and automatically, any classes that extend that class and inherit the methods, will have their return types set to their respective thistype. Like so:

使用TypeScript 1.7 中的Polymorphic this,正如我在此处发现的,我们可以在返回类型为 的类中定义一个方法this,并且自动地,扩展该类并继承这些方法的任何类都将其返回类型设置为各自的this类型. 像这样:

class Model {
  save():this {    // return type: Model
    // save the current instance and return it
  }
}

class SomeModel extends Model {
  // inherits the save() method - return type: SomeModel
}

However, what I'm after is to have an inherited staticmethod with a return type referencing the class itself. It's best described in code:

但是,我所追求的是拥有static一个返回类型引用类本身的继承方法。最好在代码中描述:

class Model {
  static getAll():Model[] {
    // return all recorded instances of Model as an array
  }

  save():this {
    // save the current instance and return it
  }
}

class SomeModel extends Model {
  // inherits the save() method - return type: SomeModel
  // also inherits getAll() - return type: Model (how can we make that SomeModel?)
}

Perhaps I'll have to think of a different way to implement this, since Polymorphic thisin TypeScript 1.7 does not support staticmethods by design.

也许我必须想出一种不同的方式来实现这一点,因为thisTypeScript 1.7 中的Polymorphic不支持设计static方法。

EDIT: I guess we'll see how this Github issue wraps up: https://github.com/Microsoft/TypeScript/issues/5863

编辑:我想我们会看到这个 Github 问题是如何结束的:https: //github.com/Microsoft/TypeScript/issues/5863

回答by mrm

This is doable in TypeScript 2.0+. By using an inline { new(): T }type to capture this, you'll get what you wanted:

这在 TypeScript 2.0+ 中是可行的。通过使用内联{ new(): T }类型来捕获this,你会得到你想要的:

type Constructor<T> = { new (): T }

class BaseModel {
  static getAll<T>(this: Constructor<T>): T[] {
    return [] // dummy impl
  }

  /**
   * Example of static method with an argument:
   */
  static getById<T>(this: Constructor<T>, id: number): T | undefined {
    return // dummy impl
  }

  save(): this {
    return this // dummy impl
  }
}

class SubModel extends BaseModel {}

const sub = new SubModel()
const savedSub: SubModel = sub.save()

// Behold: SubModel.getAll() returns SubModels, not BaseModel
const savedSubs: SubModel[] = SubModel.getAll()

Note that getAllstill expects no arguments with this typing.

请注意,getAll这种类型仍然不需要参数。

For more information, see https://www.typescriptlang.org/docs/handbook/generics.html#using-class-types-in-genericsand https://stackoverflow.com/a/45262288/1268016

有关更多信息,请参阅https://www.typescriptlang.org/docs/handbook/generics.html#using-class-types-in-genericshttps://stackoverflow.com/a/45262288/1268016

回答by Brian M. Hunt

Based on the simplest answerto the GitHub issue, you can use InstanceType<>like this:

基于最简单的回答GitHub的问题,你可以使用InstanceType<>这样的:

class Foo {
    static create<T extends typeof Foo>(this: T): InstanceType<T> {
        return new this() as InstanceType<T>
    }

    static getAll<T extends typeof Foo>(this: T): Array<InstanceType<T>> {
        return []
    }
}

class Bar extends Foo { }

const a = Bar.getAll() // typeof a is Bar[]
const b = Bar.create() // typeof b is Bar.

Where I threw in the createfunction just for illustration, from the linked GitHub example.

create从链接的 GitHub 示例中放入函数只是为了说明。

回答by Nypan

What are you expecting this static method to return in the inherited subclass? Is it something like this:

你期望这个静态方法在继承的子类中返回什么?是不是像这样:

class A {
    private static _instances = new Array<A>();
    static instances(): A[] { return A._instances; }
    constructor() { A._instances.push(this); }
}

class B extends A {

    static instances(): B[] { 
        return <B[]>(A.instances().filter(i => i instanceof B)); 
    }
    constructor() { super(); }; 
}

var a = new A();
var b = new B();

console.log(
     "A count: " + A.instances().length + 
    " B count: " + B.instances().length);

This will output "A count: 2 B count: 1". Or what are you expecting?

这将输出“A 计数:2 B 计数:1”。或者你在期待什么?