One interesting approach is to utilize a (K | V)[][]
as ReadonlyArray<[K, V]>
within a Map constructor. Suppose that V represents an interface IItem
, while K is a basic type of number
.
interface IItem {
key: number;
val: string;
}
const items = [[1, {key: 1, val: "a"}]]
const ze_map = new Map<number, IItem>(items);
console.log(JSON.stringify([...ze_map]));
By default, typescript will interpret the type of items as : (number | IItem)[][]
. This will result in an error:
Argument of type '(number | { key: number; val: string; })[][]' is not assignable to parameter of type 'ReadonlyArray<[{}, {}]>'.
Type '(number | { key: number; val: string; })[]' is missing the following properties from type '[{}, {}]': 0, 1
Fortunately, we can explicitly define the type as Array<[number, IItem]>
to satisfy the requirements of Map
.
const items2 : Array<[number, IItem]> = [[1, {key: 1, val: "a"}]]
const ze_map2 = new Map<number, IItem>(items2);
console.log(JSON.stringify([...ze_map]));
This solution works perfectly. Now, let's address a common issue - what if we cannot enforce the type?
const arr = [
{ key: 3, val: 'bar' },
{ key: 5, val: 'world' }
];
const result: Array<[number, IItem]> = arr.map(i => ([i.key, i]));
const ze_map3 = new Map(result);
console.log(JSON.stringify([...ze_map]));
In this scenario, the code fails because
(number | { key: number; val: string; })[][]
does not align with Array<[number, IItem]>
. So, how do we effectively use (K | V)[][]
as ReadonlyArray<[K, V]>
in a Map?
You can experiment with all the code snippets online here
I studied both How to define Map with correlation between a key type and a value type, while they both are unions and Typescript Map<enum, set<enum>> "No overload matches this call", but I don't get why? without finding a definitive solution.
I also referred to the MDN entry on Map, which suggests that it should function correctly. Testing in pure JS confirms this:
var arr = [
{ key: 3, val: 'bar' },
{ key: 5, val: 'world' }
];
var result = arr.map(i => [i.key, i]);
const ze_map = new Map(result);
console.log(JSON.stringify([...ze_map]));
Give it a try here!