Search code examples
typescriptdictionarytyping

How to type-hint a Map whose keys are classes and values are instances of those classes?


I have a map whose keys are classes and their values are instances of those respective classes.

// JavaScript code
class A {};
class B {};

const map = new Map();

map.set(A, new A);
map.set(B, new B);

How do I type-hint this map correctly in typescript?


Solution

  • You'll need a custom map definition because the standard one expects keys to be of the same type and values as well, also it doesn't allow to setup any relation between the two.

    So it could be something like:

    type Constructor = new (...args: any) => any;
    
    interface ConstructorMap {
        clear(): void;
        delete(key: Constructor): boolean;
        get<K extends Constructor>(key: K): InstanceType<K> | undefined;
        has(key: Constructor): boolean;
        set<K extends Constructor>(key: K, value: InstanceType<K>): this;
        readonly size: number;
    }
    
    class A { a = '' };
    class B { b = 1 };
    
    const map: ConstructorMap = new Map();
    
    map.set(A, new A);
    map.set(B, new B);
    
    const a = map.get(A) // A | undefined
    
    // Expect error: Argument of type 'B' is not assignable to parameter of type 'A'
    map.set(A, new B);
    

    Playground

    Docs on InstanceType<Type> utility