3

I am designing a custom Model structure for my NodeJS project. I have created a base class named Model which is inherited by other model classes. The base model class will have a set of properties that needs to be accessed by the methods. The properties will get overwritten by child classes as shown in the examples below(by User model).

There is a table property which I need to access from both static as well as non-static methods as such:

Case 1: Base model class has non-static property table.

class Model {
  protected table = '';

  public static find(id: number) {
    // I want to have table name in here but cant.
  }

  public save() {
    // I am able to get table name in here `this`.
  }
}

class User extends Model {
  protected table = 'users'; // overwriting parent's table property

  // list of other non static properties in here

  constructor(user: UserSchema) {
    // assign non static properties from here
  }
}

Case 2: Base model class has static property table.

class Model {
  protected static table = '';

  public static find(id: number) {
    // I am able to get table name in here using `this`.
  }

  public save() {
    // I want to have table name in here but cant.
  }
}

class User extends Model {
  protected static table = 'users'; // overwriting parent's table property

  // list of other non static properties in here

  constructor(user: UserSchema) {
    // assign non static properties from here
  }
}

I tried changing the static and non-static nature of table property but whenever I switch, there occurs two scenarios.

  • Either static method can only access static property.
  • Or non-static method can only access non-static property.

I could access static property using class name(e.g. Model.table) but it will result base model's empty value("") and I need the User's overloaded table value('users') to work.

I want to have control over both the scenarios where I could get the properties interchangibly(accessing static property from non static method as well as static property from non static method). How can I acheive this behaviour? Any suggestion is appreciated.

Vectrobyte
  • 1,408
  • 12
  • 30
  • You can access static from non-static by `Model.table` in case 2 `save`. But you cannot refer to an instance property in a static context without an instance at-hand. – ford04 Feb 12 '20 at 10:16
  • @ford04 Yes, that's the problem I am facing – Vectrobyte Feb 12 '20 at 10:28
  • @ford04 I was able to do that without any errors, but the value of table `users` set from User model is not received in the base class. It returns empty string(which is the default value of the property). I want to have the value accessed in here as well. Much like the laravel framwork where the table name set from child classes gets available to the base eloquent models. – Vectrobyte Feb 12 '20 at 10:45

1 Answers1

1

Concerning Case 1:

Instance properties like table are not accessible from a static context. You would either have to make table a static protected static table = '' or let find become an instance method public find(id: number){...}.

Concerning Case 2:

table is a static class property and will be set on the constructor function of User itself. It is not related to table in Model, therefore it is not possible to override it via protected static table = 'users' in User. You can check the ES5 transpiled code to get a feeling, how static is implemented in classes.

There is an (untyped) way to get an overridden static property from parent by invoking this.constructor.table in the Model base class. But I think, what you want and what is a cleaner solution, is to make table a (possibly abstract) instance property, which provides the the child value from the parent:

class Model {
  protected table = "";

  public save() {
    console.log(this.table)
  }
}

class User extends Model {
  protected table = 'users';
}

class Developer extends Model {
  protected table = 'devs';
}
new Developer().save() // "devs"
new User().save() // "users"

sample

ford04
  • 66,267
  • 20
  • 199
  • 171
  • Okay, I get it, but now, there's this `public static find()` function where I need to access the non static property `table`. Now what can I do to achieve that behaviour in the same example code you've provided? (or I am simply expecting the unexpected) – Vectrobyte Feb 12 '20 at 15:05
  • 1
    Well, as said, that is not possible - it is how OOP in JS and all other languages work. You would have to rethink your approach - e.g. why does it have to be a static `find`, can the `table` properties be stored as constants in a module etc. . I gave you some alternatives in the answer here and now have the slight feeling, that it becomes more of an architecture design beyond question scope. Hope, it gave some inspiration nonetheless. – ford04 Feb 12 '20 at 16:46
  • Well I appreciate it. Thank you for your time. – Vectrobyte Feb 13 '20 at 03:08
  • You are welcome. If something is still open, feel free to open a new question focused more on how to implement your model. Good luck! – ford04 Feb 13 '20 at 06:07