简体   繁体   English

如何从静态方法将新的`this`传递给静态方法?

[英]How to pass a newable `this` to a static method from a static method?

How do I pass a newable this to a static method from a static method? 我如何通过一个newable this从一个静态方法静态方法?

TypeScript Playground TypeScript Playground

abstract class Model {
  public static convert<T extends Model>(model: new () => T, data: any | any[]) { 
    return new model()
  }

  public static all<T extends Model>(): Promise<[]> {
    let items: any[] = []
    return Model.convert(this, items)
                      // ^--- Error is here
  }
}

The resulting JavaScript works, and I get an instance of A , however typescript complains with this error: 生成的JavaScript工作,我得到一个A的实例,但是typescript抱怨这个错误:

Argument of type 'typeof Model' is not assignable to parameter of type 'new () => Model'. 类型'typeof Model'的参数不能分配给'new()=> Model'类型的参数。

 class Model { static convert(model, data) { return new model() } static all() { let items = []; return Model.convert(this, items); } } class A extends Model { } console.log(A.all(), A.all().constructor.name); 

This would normally work if Model were not abstract . 如果Model不是abstract这通常会起作用。 If Model was not abstract this (which is typed as typeof Model ) would have the new () => Model constructor, but since it is abstract, it does not have a callable constructor. 如果Model没有抽象this (这是类型为typeof Model )将有new () => Model构造,但由于它是抽象的,它不具备一个可调用构造函数。

The simple solution is to add an annotation for this in the static method: 简单的解决方案是在静态方法中this添加注释:

abstract class Model {
  public static convert<T extends Model>(model: new () => T, data: any | any[]): T[] { return null!; }

  public static all<T extends Model>(this: new () => T): Promise<T[]> {
    let items: any[] = []
    return Promise.resolve(Model.convert(this, items));
  }
}

class A extends Model { }


console.log(Model.all()) // err since Model does not have a ctor
console.log(A.all(), A.all().constructor.name)

Play

This will make all un-callable for Model which is probably what you want anyway. 这将使Model all不可调用,这可能是你想要的。

Edit 编辑

Since in your actual use case you want to call static methods from other static methods we need a slightly more complex annotation for this . 由于在实际使用情况下,你想调用其他静态方法静态方法,我们需要一个稍微复杂的注释this The previous version just keeps the constructor signature and none of the static members. 以前的版本只保留构造函数签名而不保留静态成员。 You need the static members represented by typeof Model in the annotation. 您需要在注释中使用由typeof Model表示的静态成员。 The simplest way to do this is to add typeof Model in an intersection with the constructor signature we previously defined ( (new () => T) ) basically adding a constructor to the abstract class. 最简单的方法是在与我们之前定义的构造函数签名的交集中添加typeof Model(new () => T) )基本上将构造函数添加到抽象类。


type NonAbstracModel<T extends Model> = (new () => T) & typeof Model
abstract class Model {
  public static convert<T extends Model>(model: NonAbstracModel<T>, data: any | any[]): T { return new model() }

  public static all<T extends Model>(this: NonAbstracModel<T>): T {
    let items: any[] = []
    return Model.convert(this, items)
  }

  public static find<T extends Model>(this: NonAbstracModel<T>, primaryKey: string | object) { }

  public static firstOrFail<T extends Model>(this:NonAbstracModel<T>) {
    this.find('abc')
  }

}

class A extends Model {}

console.log(A.all(), A.all().constructor.name)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM