3

I'm trying to merge enum maps, the code runs:

enum One {
    a = 'a',
}

enum Two {
    aa = 'aa',
}

enum Three {
    aaa = 'aaa',
}

type unit = One | Two | Three;

const twoFromOne: Map<Two, One> = new Map([[Two.aa, One.a]]);
const threeFromTwo: Map<Three, Two> = new Map([[Three.aaa, Two.aa]]);
const combined: Map<unit, unit> = new Map([
    ...twoFromOne,
    ...threeFromTwo,
]);

but I get a typescript compiler error:

const twoFromOne: Map<Two, One>
No overload matches this call.
  Overload 1 of 3, '(iterable: Iterable<readonly [Two, One]>): Map<Two, One>', gave the following error.
    Argument of type '([Two, One] | [Three, Two])[]' is not assignable to parameter of type 'Iterable<readonly [Two, One]>'.
      The types returned by '[Symbol.iterator]().next(...)' are incompatible between these types.
...

I don't understand the error, is it saying one map is being assigned into another instead of a merge?

Link to TS playground

WBC
  • 1,854
  • 4
  • 21
  • 34

2 Answers2

2

The problem is the following: Trys to create a Map that has type Map<Two, One>

TypeScript somehow infers the type based on only the first map that you provide ( ...twoFromOnw). You can add <unit, unit> to the MapConstructor (right side), so TypeScript will not infers thats type, rater use Map<unit, unit>:

const combined: Map<unit, unit> = new Map<unit, unit>([
    ...threeFromTwo,
    ...twoFromOne,
]);
0

I just thought maybe it will be helpfull:

enum Point {
    a = 'a',
    aa = 'aa',
    aaa = 'aaa',
}

const twoFromOne: Map<Point.aa, Point.a> = new Map([[Point.aa, Point.a]]);
const threeFromTwo: Map<Point.aaa, Point.aa> = new Map([[Point.aaa, Point.aa]]);

type Overloading = Map<Point.aa, Point.a> & Map<Point.aaa, Point.aa>

const createMap = <K1 extends Point, V1 extends Point, K2 extends Point, V2 extends Point>(fst: Map<K1, V1>, scd: Map<K2, V2>): Overloading =>
    new Map<any,any>([ ...fst, ...scd])

const result = createMap(twoFromOne, threeFromTwo)

result.set(Point.aa, Point.a) // ok
result.set(Point.aaa, Point.aa) // ok
result.set(Point.aaa, Point.a) // expected error
result.set(Point.aa, Point.aa) // expected error


result.get(Point.aa) //  Point.a | undefined
result.get(Point.aaa) //  Point.aa | undefined
result.get(Point.a) // expected error