It seems there may be a slight misunderstanding regarding how classes are categorized.
Let's consider, for simplicity's sake, two classes ClassA
and ClassB
.
class ClassA {
constructor() {
console.log("Class A");
}
}
class ClassB {
constructor() {
console.log("Class B");
}
}
Creating the map object is straightforward, but it might have been helpful to outline an interface specifying what this object should contain. However, following your example, I will proceed without one.
const map = {
a: ClassA,
b: ClassB,
};
Now comes the challenging part - Typings.
Firstly, I aim to extract all keys of the map object.
For this purpose, I will define a new type called: Keys
// Type includes: "a" | "b"
type Keys = keyof typeof map;
Next, I need all the corresponding values for each key.
To achieve this, I will create a new type at the index of Keys
.
// Type includes: typeof ClassA | typeof ClassB
type Values = typeof map[Keys];
The getter function should return an instance of a class T
. However, the Values
type contains all classes as typeof ClassA | typeof ClassB
, which translates to
new() => ClassA | new() => ClassB
.
Therefore, the type of
ClassA | ClassB
is not compatible.
To address this, let's create a separate type to resolve the issue. This type should yield the instance type of a class - simply ClassA
or ClassB
.
In other words, the return type of the new SomeClass()
operation.
type ReturnType<T> = T extends new() => infer R ? R : never;
If you wish to learn more about conditional types in TypeScript, I recommend checking out this blog post:
Let's incorporate the final piece:
const conf = {};
const getter = (ver: Keys): ReturnType<Values> => new map[ver]();
Just a heads up: I renamed VersionMap
to Values
and Version
to Keys
for clarity on their intended purposes. Feel free to adjust these names to suit your preferences.