3
import Collection from 'collection'

class Model {
}

class Book extends Model {
    static collection = new Collection<Book>('books')
}

I would like to move the collection definition from Book to Model:

import Collection from 'collection'

class Model {
    static _collection

    static get collection() {
         let typename = this.name // = Book
         if(!this._collection) {
             this._collection = new Collection<...>('books')
         }
         return this._collection
    }
}

class Book extends Model {
}

I can get the class name (Book) inside the parent class (Model) by using this.name. But how can I refer to the type of Book to use it with new Collection<>?

Chris
  • 13,100
  • 23
  • 79
  • 162

1 Answers1

-2

The collection member is static. A static member always belongs to the type it is being declared in, so by moving the collection to the base type Model, you are essentially making all subtypes of Model use the exact same collection (the one declared in Model).

So if all subtypes of Model use the same collection, then it does not make sense to have the type of Book.collection be Collection<Book> when it is actually a Collection<Model>.

I would suggest you to think over what you are trying to achieve here. Usually, static members may not be the best idea, so maybe consider doing something else there.


That all being said, if the collection wasn’t a static member, you would still have a conceptual problem here: The point of the static typing is to have the type information at compile time. When compiled down to JavaScript, that collection won’t be typed at all and it will not enforce the type information that still exists at compile time.

That’s why you simply cannot use type information that only exists at runtime. And this.name will be evaluated at compile time: There is no real way for the compiler to now that this will be Book and that the collection would be of that type then.

The solution for variable type support are generics, just like the collection already does. So if you would want a member inside Model that had a variable type, then you would need to make Model generic:

class Model<T> {
    private _collection : T[];

    public get collection() {
        if (!this._collection) {
            this._collection = new Collection<T>();
        }
        return this._collection;
    }
}

class Book extends Model<Book> { … }

Now Book would have a Collection<Book> member, available at compile time.

poke
  • 369,085
  • 72
  • 557
  • 602