I would like to store some informations in a TypeScript (JavaScript) map under a key which reflects the type of a class. This is because the stored data is actually static and applies per type, not per instance.
Here's how I have declared the Map atm:
private static followSetsByATN: Map<number, FollowSetsPerState> = new Map();
However, number
should be a class type instead. How can this be achieved?
TypeScript treats a class as both value and type. This implicit type declared by TypeScript describes the shape of the instance a class produces. Therefore when a class is used as a type, such as using let value :Class annotation, TypeScript checks if the value has all the public properties of the Class .
We use the get() method of a map in TypeScript to get the value for a key in a map. A map is a key-value pair data structure.
Use Map type and new keyword to create a map in TypeScript. let myMap = new Map<string, number>(); To create a Map with initial key-value pairs, pass the key-value pairs as an array to the Map constructor.
To define a Map with array values in TypeScript, type the map to have keys of a specific type and set the values to have an array type, e.g. const map1 = new Map<number, string[]>() . All of the key-value pairs in the Map must conform to the specified type. Copied!
If you have an object ({}
) as a map then the keys must be strings (or numbers which are converted to strings automatically).
In this case you can use the toString()
method:
class A { }
console.log(A.toString());
Will print:
function A() {
}
You can also use the name
property:
console.log(A.name); // "A"
You can also override the toString()
method to return something of your own:
class A {
static toString() {
return "class A";
}
}
console.log(A.toString()); // "class A"
And then:
let m = {} as { [name: string]: string };
m[A.toString()] = "something";
// or
m[A.name] = "something";
If you are using a Map
then all of the above still work, but you are not restricted to have string keys therefor you can use the class itself:
let m = new Map<{ new (): A }, string>();
m.set(A, A.toString());
console.log(m.get(A)); // "class A"
If you have an instance of a class, you can get the class using the constructor
property:
let a = new A();
...
m.set(a.constructor, SOME_VALUE);
The constructor
property comes from object
and it looks like so:
interface Object {
/** The initial value of Object.prototype.constructor is the standard built-in Object constructor. */
constructor: Function;
...
}
So you always get a Function
and you'll need to cast:
m.set(a.constructor as typeof A, SOME_VALUE);
As you probably don't know the type of the class, you'll need to do something else.
You can cast to any
, but that's not very pretty.
Here's a working solution that should work well for you:
interface Base { }
type BaseContructor = { new (): Base };
class A implements Base { }
class B implements Base { }
let m = new Map<BaseContructor, string>();
let a = new A();
let b = new B();
m.set(a.constructor as BaseContructor, "value");
m.set(b.constructor as BaseContructor, "value");
(code in playground)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With