I think I may have stumbled into a situation where what I want is best described by having both static
and abstract
on a member of an abstract class, but that doesn't seem to be possible in typescript.
The closest I can get is the below:
abstract class A {
s: string;
n: number;
static identifier: string;
constructor(s: string, n: number) {
this.s = s;
this.n = n;
}
}
class B extends A {
static identifier: string = "B";
}
class C extends A {
static identifier: string = "C";
}
function identifyAndInstantiate(identifier: string, classes: (typeof A)[]) {
var identifiedClass = classes.find((classCandidateConstructor: typeof A) => { return identifier == classCandidateConstructor.identifier });
if (!identifiedClass) return;
//error here: Cannot create an instance of an abstract class.(2511)
var instance = new identifiedClass("foo", 12);
}
var classes: (typeof A)[] = [
B,
C
]
I've tried a variety of different approaches to the collection type. The closest I could get working was a Map from the static member type to instances of the class, but then you have to individually map the values to their classes.
Another thing I tried was to use a Newable<T>
type that describes its constructor, but this removes the ability to refer to the subclass' static properties (as does seemingly anything else that makes the constructor available).
Is there a way to both refer to a subclass' static properties and its constructor when having retrieved it from a collection of classes?
Your code works almost as-is, with the following changes:
subclass.identifier
unless that property is in the type of subclassesOfA
typeof A
but you can instantiate a { new(): A }
function foo(subclassIdentifier: string, subclassesOfA: {
identifier: string,
new (): A
}[]): void {
let subclass = subclassesOfA.find((subclass) =>
subclass.identifier == subclassIdentifier);
if (subclass) {
let instance = new subclass();
// ...
}
}