TypeScript: self-referencing return type for static methods in inheriting classes

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

Leave a Comment

tech