Nathaniel Tucker
Nathaniel Tucker

Reputation: 597

Is it possible to get InstanceType<T> to work on an abstract class?

I obviously want to allow allow it to refer to implementations not the abstract itself, while still only relying on the abstract interface definitions.

Upvotes: 5

Views: 560

Answers (1)

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

Reputation: 249876

You can use the type of the prototype instead of the type of the constructor return.

type AbstractInstanceType<T> = T extends { prototype: infer U } ? 
    U : never


abstract class Foo{
    foo:number
}

declare var foo: AbstractInstanceType<typeof Foo>;
foo.foo //ok

You might be better off using a constructor signature where you would have used typeof AbstractClass. InstanceType will work on this : new (... a:any[]) => AbstractClass

If you want to create a static factory method on an abstract class this is what will work :

abstract class Foo{
    foo: number
    static create<T extends Foo>(this: new () => T) {
        return new this();
    }

    static createWithArgs<T extends Foo, A extends any[]>(this: new (...a: A) => T, ...a: A) {
        return new this(...a);
    }
}
class Bar extends Foo { }
class Baz extends Foo {
    constructor(public n: string) {
        super();
    }
}

Bar.create()
Baz.createWithArgs("")

Upvotes: 6

Related Questions