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

后端 未结 3 547
野的像风
野的像风 2020-12-03 07:12

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

相关标签:
3条回答
  • 2020-12-03 07:27

    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.

    0 讨论(0)
  • 2020-12-03 07:34

    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/generics.html#using-class-types-in-generics and https://stackoverflow.com/a/45262288/1268016

    0 讨论(0)
  • 2020-12-03 07:41

    What are you expecting this static method to return in the inherited subclass? Is it something like this:

    class A {
        private static _instances = new Array<A>();
        static instances(): A[] { return A._instances; }
        constructor() { A._instances.push(this); }
    }
    
    class B extends A {
    
        static instances(): B[] { 
            return <B[]>(A.instances().filter(i => i instanceof B)); 
        }
        constructor() { super(); }; 
    }
    
    var a = new A();
    var b = new B();
    
    console.log(
         "A count: " + A.instances().length + 
        " B count: " + B.instances().length);
    

    This will output "A count: 2 B count: 1". Or what are you expecting?

    0 讨论(0)
提交回复
热议问题