【问题标题】:How to use a static function of a class passed as a parameter如何使用作为参数传递的类的静态函数
【发布时间】:2020-04-13 01:09:40
【问题描述】:

基本上,我需要使用作为参数传递的类的静态函数:

编辑:

我没有正确解释自己,希望你能通过这个例子理解我。

最小的可重现示例。

const TABLES = {
  bike: [],
  car: []
};

class Vehicles {
  static table = "";
  static getAll<T extends Vehicles>(): T[] {
    return TABLES[this.table];
  }
}

class Bike extends Vehicles {
  static table = "bike";
}

class Car extends Vehicles {
  static table = "car";
}

function getVehicleByClass<T extends Vehicles>(Vehicle: typeof T) { // 'T' only refers to a type, but is being used as a value here.
  Vehicle.getAll();
}

getVehicleByClass<Car>(Car);

【问题讨论】:

  • 我试图在下面提供帮助,但更完整(且可运行)的minimal reproducible example 将有助于澄清问题,并可能会带来更好的解决方案。
  • 附注:您的createAssociations 中没有await。除非它使用await,否则没有理由使用async
  • @T.J.Crowder 谢谢你的回答!我更新了我的问题,以便您可以正确理解我。顺便说一句,异步不是必需的。

标签: typescript class types


【解决方案1】:

更新答案

...在对问题进行编辑之后。

泛型类型应该扩展typeof Vehicles而不是Vehicles

function getVehicleByClass<T extends typeof Vehicles>(Vehicle: T) {
  Vehicle.getAll();
}

On the playground

也就是说,我可能会给自己一个类型为typeof Vehicles

type VehiclesType = typeof Vehicles;

然后:

function getVehicleByClass<T extends VehiclesType>(Vehicle: T) {
// −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−^
  Vehicle.getAll();
}

On the playground

...只是因为我认为更小的部分更好。 :-D

原答案

(我离开这个只是因为你说它对你正在工作的其他一些东西很有用......)

你应该工作,我怀疑这里真正的问题是你没有输入 Object.values (在 ES2017 中添加)。您需要检查您的 tsconfig.json 以确保您的 lib 选项是 ES2017 或更高版本。

如果您有Object.valuesthis works 的类型:

class Model {
    static associate(models: { [key: string]: typeof Model }): { [key: string]: typeof Model } {
        return { foo: Model };
    }
}
class Model2 extends Model {
}
class Model3 extends Model {
}

async function createAssociations(models: { [key: string]: typeof Model }): Promise<void> {
  Object.values(models).forEach(model => {
    if (model.associate) {
      model.associate(models);
    }
  });
}

...虽然我认为我会为 {[key: string]: typeof Model} 类型使用一个类型,因为您在多个地方使用它:

type ModelValuesObject = { [key: string]: typeof Model };

然后:

class Model {
    static associate(models: ModelValuesObject): ModelValuesObject {
        return { foo: Model };
    }
}
class Model2 extends Model {
}
class Model3 extends Model {
}

async function createAssociations(models: ModelValuesObject): Promise<void> {
  Object.values(models).forEach(model => {
    if (model.associate) {
      model.associate(models);
    }
  });
}

如果您想要最小更改,您可以键入forEach 回调的model 参数:

Object.values(models).forEach((model: typeof Model) =>

这将允许您对 model 值中的类使用 static 方法。

但是 TypeScript 可以推断它。我在这里取了{[key: string]: typeof Model} 并给它起了一个方便的名字,以便我们可以重复使用它:

type ModelValuesObject = { [key: string]: typeof Model };

那就是:

class Model {
    static associate(models: ModelValuesObject): ModelValuesObject {
        return { foo: Model };
    }
}
class Model2 extends Model {
}
class Model3 extends Model {
}

async function createAssociations(models: ModelValuesObject): Promise<void> {
  Object.values(models).forEach(model => {
    if (model.associate) {
      model.associate(models);
    }
  });
}

On the playground

【讨论】:

  • 感谢您的解决方案!它在其他示例中就像一个魅力,但是,在这种情况下,.associate 没有在类 Model 中声明。我正在将它从 JavaScript 迁移到 TypeScript,并且我曾经在其他文件中为某些类声明该属性。我只需要扩展类并将.associate 设置为新功能,但是我面临着这个新问题(已编辑问题中显示的问题)。
  • 这个问题困扰了我几个项目,非常感谢!!!
  • @Zeswen - 不用担心!我刚刚意识到我添加的类型不是必需的(无论如何我可能会使用它,但这不是必需的)。可以只是function getVehicleByClass&lt;T extends typeof Vehicles&gt;(Vehicle: T)
  • @Zeswen - 顺便说一句,你的问题增加了我对 TypeScript 的理解,所以......谢谢! :-)
猜你喜欢
  • 2011-12-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-02
  • 2016-03-17
  • 2020-04-20
  • 1970-01-01
  • 1970-01-01
  • 2016-07-14
相关资源
最近更新 更多