0

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?

Antonio Gamiz Delgado
  • 1,871
  • 1
  • 12
  • 33
  • Please consider modifying the code in this question so as to constitute a [mcve] which, when dropped into a standalone IDE like [The TypeScript Playground](https://tsplay.dev/ND5dRm), clearly demonstrates the issue you are facing. This will allow those who want to help you to immediately get to work solving the problem without first needing to re-create it. And it will make it so that any answer you get is testable against a well-defined use case. – jcalz Mar 30 '21 at 19:01
  • I know that, but I think it's not possible in this case. – Antonio Gamiz Delgado Mar 30 '21 at 19:06
  • You can't demonstrate the issue with code? – jcalz Mar 30 '21 at 19:09
  • Not with working code. If I had working code I would not have a problem. – Antonio Gamiz Delgado Mar 30 '21 at 19:11
  • 1
    Make a minimal example that fails to compile in the same way as your code, then – Jonas Høgh Mar 30 '21 at 19:16
  • Indeed, it would be cruel and/or pointless of me to ask you to fix the problem yourself. A [mcve] is not supposed to be "working code"; it's supposed to be self-contained code that, when someone else uses it, gives them the same problem you are seeting. Maybe in your case it's like [this](https://tsplay.dev/m02xnw)? Maybe something else? – jcalz Mar 30 '21 at 19:17
  • does `this.model.get(...)` returns what exactly? – WilsonPena Mar 30 '21 at 19:21
  • I imagine it runs a query or something like that – WilsonPena Mar 30 '21 at 19:22
  • @jcalz you're right, I have updated my answer to show my current error. – Antonio Gamiz Delgado Mar 30 '21 at 19:34
  • @WilsonPena it retuns an internal object of denodb library, I think it does not matter. – Antonio Gamiz Delgado Mar 30 '21 at 19:34
  • I'm still not getting the behavior you're talking about, likely because of the import. [See here](https://tsplay.dev/wEVx4N). Do you have a link to a web IDE project that shows the error happening? Or could you try to remove the external dependency, maybe – jcalz Mar 30 '21 at 19:57
  • I think you cannot run deno in a web ide yet. – Antonio Gamiz Delgado Mar 30 '21 at 20:02
  • I'm more concerned with the compiler warning than runtime behavior, and I couldn't reproduce that. It looks like you found a workaround, but if you're interested in some other answer then I'd be happy you take a look if you can make a [mcve] that works in a standalone environment (so you'd replace the import with a type that behaves similarly in the compiler). – jcalz Mar 31 '21 at 13:31

2 Answers2

1

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();
Antonio Gamiz Delgado
  • 1,871
  • 1
  • 12
  • 33
0

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

Jonas Høgh
  • 10,358
  • 1
  • 26
  • 46
  • :(. I had found this question too https://stackoverflow.com/questions/55107657/dynamically-call-static-method-on-variable-typescript-theory-implementation where it gave an alternative. I had hoped that it had been solved by now. Thanks – Antonio Gamiz Delgado Mar 30 '21 at 20:12