Reputation: 294
It's too complicated to explain what I need to get, let me show a code with some comments.
I think it will be much clearer.
abstract class Base {
abstract getType(): string;
static test(): string[] {
return [];
}
}
class Foo extends Base {
foo = '123';
getType(): string {
return "foo";
}
static test(): string[] {
return ["a", "b", "c"]
}
}
class Bar extends Base {
bar = '321';
getType(): string {
return "bar";
}
static test(): string[] {
return ["a", "b", "c"]
}
}
// The following map is a temporary solution just to show what I want to get
// I supposed the map has to have another type instead of "any"
const m = new Map<string, any>();
m.set("foo", Foo);
m.set("bar", Bar);
console.log(m.get('foo').test()); // << I need to have access to static functions and it works with "any" type
function func(it: Base) {
const baseType = it.getType();
if (m.has(baseType)) {
const cl = m.get(baseType);
const item = it as cl; // << error: 'cl' refers to a value, but is being used as a type here. Did you mean 'typeof cl'?
console.log(item);
}
}
// I know I could do it by the following way, but in this case if I will want to add a few more new classes I will have to update many palces in the code.
// I'd like just to add a new class into the map without updating the entire code.
function func2(it: Foo|Bar) {
const baseType = it.getType();
console.log(baseType, it)
}
const fooInst = new Foo();
func(fooInst);
func2(fooInst);
What I want to get:
getType()
.Upvotes: 0
Views: 68
Reputation: 354
In TypeScript, a list of classes can be achieved using a union.
In order for a union to work with static members of a class, you should also use the typeof
keyword.
In order to cast to a type based on a property of the base object, you need to use type guards.
A type guard is a check that makes sure that a given argument is of the type. This can either be the typeof
keyword, i.e. typeof arg == "string"
, or a user-defined typeguard;
function isArgString(arg: any): arg is string => {
return typeof arg == "string";
}
To recap, the way to make your map work is using a union, and for your casting, use typeguards:
type myUnion = typeof Foo | typeof Bar;
export const isBar = (arg: Base): arg is Bar => {
return arg.getType() === 'bar';
}
export const isFoo = (arg: Base): arg is Foo => {
return arg.getType() === 'foo';
}
Upvotes: 2