Home > Software engineering >  Mapped type from array with key change
Mapped type from array with key change

Time:10-16

Let's say that I have this:

export type ParamDecl = ["input" | "output", "float" | "int" | "bool", string][];

const params: ParamDecl = [["input", "float", "x"], ["output", "float", "a"], ["input", "int", "y"], ["output", "bool", "b"]];

And I want to turn it into this:

export type Converted = {
  x: "float",
  a: "float",
  y: "int",
  b: "bool"
};

By using generics and mapped types (yes, I am discarding the "input" | "output" part; I'll think about that later). I want to be able to do this:

let dict: AsDictionary<typeof params>;

I tried using the following mapped type:

export type AsDictionary<X extends ParamDecl> = { [K in keyof X as X[K][2]]: X[K][1] };

But I get 2 errors; I think the second one is a consequence of the first one.

The errors I get.

Type 'X[K][2]' is not assignable to type 'string | number | symbol'.
  Type 'X[keyof X][2]' is not assignable to type 'string | number | symbol'.
    Type 'X[string][2] | X[number][2] | X[symbol][2]' is not assignable to type 'string | number | symbol'.
      Type 'X[string][2]' is not assignable to type 'string | number | symbol'.ts(2322)
Type '2' cannot be used to index type 'X[K]'.ts(2536)

I think X[string][2] should be more or less valid; the only issue if any is that it should be X[number][2] if anything, because the input type it's an array.

What am I doing wrong?

CodePudding user response:

The problem here is that you are using keyof X in the mapped type. X is an array which has dozens of other properties like push or pop or length. You can't index those with 2 as they are not tuples/arrays.

You need to map over the union of elements in X with X[number].

export type AsDictionary<X extends ParamDecl> = { 
    [K in X[number] as K[2]]: K[1] 
};

Playground

  • Related