Typescript : Es6 Map TS Type Relation

Is it possible to create a sort of relation between the Key/Value types of Map ?

I mean, if I use an object, it’s easy to create something like :

type TObject = { key: string; value: number } | { key: number; value: string }
const obj = { key: 1, value: 'Something' } // Perfect
const obj = { key: 'Something', value: 1 } // Perfect
const obj = { key: 1, value: 1 } // Error

However, I don’t know how to implement this behavior for Maps

const map = new Map<string | number, number | string>();  
map.set(1, 'a'); // Perfect
map.set('a', 1); // Perfect
map.set(1, 1); // I want to display an error, with the type above : this will works since <number, number> is a possible type
map.set('a', 'a'); // I want to display an error, currently this will works since <string, string> is a possible type

Answer

Define a custom type that overrides Map to direct the call signatures to what you want.

interface CustomMap<T, U> extends Map<T | U, T | U> {
  get(key: T): U | undefined;
  get(key: U): T | undefined;
  set(key: T, value: U): this;
  set(key: U, value: T): this;
}

const map: CustomMap<string, number> = new Map();
map.set(1, 'a'); // OK
map.set('a', 1); // OK
map.set(1, 1); // error as expected
map.set('a', 'a'); // error as expected
map.size; // OK, not overridden, still a number
map.delete(1); // OK
map.delete('a'); // OK