2

I want to refer to the type of a class that extends an abstract class and has a static factory function that is implement in its abstract parent.

I learnt how to write static factories in abstract classes here: https://stackoverflow.com/a/65717206/923846.

Please consider this code:

abstract class Parent {
    public static factory<T extends Parent>(this: new (...args: any[]) => T) {
        return new this();
    }
}

class Child1 extends Parent { }
class Child2 extends Parent { }

// what specific type can i use instead of "any" here:
const arr: any[] = [ Child1, Child2 ];

let child1 = arr[0].factory();
let child2 = arr[1].factory();

I used the any type of the elements in arr.

I would like to use a specific type.

I tried to declare it like this:

type TParent = typeof Parent;

...

const arr: TParent[] = [ Child1, Child2 ];

...

// i get an error for this line:
let child1 = arr[0].factory();

I get the error "Cannot assign an abstract constructor type to a non-abstract constructor type".

So how to declare this type?

Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
obe
  • 7,378
  • 5
  • 31
  • 40

1 Answers1

2

In this case it would be the easiest to let typescript infer the types and using as const (playground):

const arr = [ Child1, Child2 ] as const;

let child1 = arr[0].factory(); // type Child1
let child2 = arr[1].factory(); // type Child2

For a generic type we would need to get rid of the abstract constructor-type and change it to a normal one to be able to instantiate via new this() (playground):

// convert the abstract constructor to a normal one and add the static functions via typeof Parent
type ParentSubClass = {new() : Parent} & (typeof Parent);

const arr: ParentSubClass[] = [ Child1, Child2 ];

let child1 = arr[0].factory(); // type Parent
let child2 = arr[1].factory(); // type Parent
Mirco S.
  • 2,510
  • 4
  • 13