简体   繁体   中英

How can I use a class type as a map key in TypeScript?

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?

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"

Edit

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 )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM