Antonio Gamiz Delgado
Antonio Gamiz Delgado

Reputation: 2113

Call a static method of a class from a generic class

I'm using denodb, an ORM for deno. As usual in ORMs, the models have some static methods, such as: get, find, etc. You define your models by creating classes that extend from a common one, provided by the ORM. In this case:

import { Model } from "https://raw.githubusercontent.com/eveningkid/denodb/master/mod.ts"
class MyModel extends Model {
  static table = "energy_meter";

  static fields = {
    id: { primaryKey: true, autoIncrement: true },
    someattribute: DataTypes.STRING,
  };
}

That works great. My problem is the following: I'm trying to create a generic data access for a ton of models that are accessed the same way (that's why I'm using a generic class). To implement this, I'm using the following class:

import { Model } from "https://raw.githubusercontent.com/eveningkid/denodb/master/mod.ts";

export abstract class InventoryDataAccess<E> {
  constructor(public model: Model) {}

  async get(id: number) {
    return ((await this.model.where("id", id).all())[0] as unknown) as E;
  }

  async getAll() {
    return ((await this.model.all()) as unknown) as E[];
  }

}

As you can see, that will not work because model attribute is an instance and the get method is static. The actual message:

This expression is not callable.
  No constituent of type 'Function | FieldValue' is callable.

That's because get is not an instance method, so it's trying to find a callable equivalent, but it does not find it. Here is the implementation of model.

So what I'm trying to do is: call a static method of a class that I need to pass as a variable to the InventoryDataAccess class.

Is this even possible? Is there any other way to have a common data access for this situation in typescript?

Upvotes: 0

Views: 1834

Answers (2)

Antonio Gamiz Delgado
Antonio Gamiz Delgado

Reputation: 2113

I have found the following workaround:

class A {
    public static staticMethod() {
        console.log("It works!");
    }
}

class B extends A {}

class C {
 constructor(public clase: typeof A) {};
 test() {
     this.clase.staticMethod();
 }
}

const c = new C(B);
c.test();

Upvotes: 1

Jonas H&#248;gh
Jonas H&#248;gh

Reputation: 10884

I don't believe this is currently possible in typescript. As you point out, you cannot call a static method in an instance context. Also, static members cannot interact with type parameters of a generic class. Here is a feature request for this, which might enable you to create a generic data access class with a static property on it, if it was implemented in a future version of typescript: https://github.com/microsoft/TypeScript/issues/34665

Upvotes: 0

Related Questions