With Polymorphic this in TypeScript 1.7, as I discovered here, we can define a method in a class with a return type of this
, and automatically, any classes that extend that class and inherit the methods, will have their return types set to their respective this
type. Like so:
class Model { save():this { // return type: Model // save the current instance and return it } } class SomeModel extends Model { // inherits the save() method - return type: SomeModel }
However, what I'm after is to have an inherited static
method with a return type referencing the class itself. It's best described in code:
class Model { static getAll():Model[] { // return all recorded instances of Model as an array } save():this { // save the current instance and return it } } class SomeModel extends Model { // inherits the save() method - return type: SomeModel // also inherits getAll() - return type: Model (how can we make that SomeModel?) }
Perhaps I'll have to think of a different way to implement this, since Polymorphic this
in TypeScript 1.7 does not support static
methods by design.
EDIT: I guess we'll see how this Github issue wraps up: https://github.com/Microsoft/TypeScript/issues/5863
Static methods are the methods in Java that can be called without creating an object of class. They are referenced by the class name itself or reference to the Object of that class.
Static Methods Are Inherited When Using ES6 Extends Syntax In JavaScript And Node.
The class or constructor cannot be static in TypeScript.
This is doable in TypeScript 2.0+. By using an inline { new(): T }
type to capture this
, you'll get what you wanted:
type Constructor<T> = { new (): T } class BaseModel { static getAll<T>(this: Constructor<T>): T[] { return [] // dummy impl } /** * Example of static method with an argument: */ static getById<T>(this: Constructor<T>, id: number): T | undefined { return // dummy impl } save(): this { return this // dummy impl } } class SubModel extends BaseModel {} const sub = new SubModel() const savedSub: SubModel = sub.save() // Behold: SubModel.getAll() returns SubModels, not BaseModel const savedSubs: SubModel[] = SubModel.getAll()
Note that getAll
still expects no arguments with this typing.
For more information, see https://www.typescriptlang.org/docs/handbook/2/generics.html#using-class-types-in-generics and https://stackoverflow.com/a/45262288/1268016
Based on the simplest answer to the GitHub issue, you can use InstanceType<>
like this:
class Foo { static create<T extends typeof Foo>(this: T): InstanceType<T> { return new this() as InstanceType<T> } static getAll<T extends typeof Foo>(this: T): Array<InstanceType<T>> { return [] } } class Bar extends Foo { } const a = Bar.getAll() // typeof a is Bar[] const b = Bar.create() // typeof b is Bar.
Where I threw in the create
function just for illustration, from the linked GitHub example.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With