Home > database >  Nested lookup types in TypeScript
Nested lookup types in TypeScript

Time:06-11

Given type

type X = {
  a: {
    b: {
      c: string;
    };
  };
};

I would expect

type Y = {
  [k in keyof X]: {
    [j in keyof X[k]]: X[k][j]['c'];
  };
};

to give me

{
  a: {
    b: string;
  };
};

However, I get error ts2536: "Type 'c' cannot be used to index type 'X[k][j]' here. But that is wrong, isn't it?

So why does the error happen and what could I do to fix it?

CodePudding user response:

The expression X[k][j] seems to be too complicated for TypeScript to remember all the relations between X, k and j. So it does not know that X[k][j] must have a property c.

We can help TypeScript accept this by adding an addtional check before indexing X.

type Y = {
  [k in keyof X]: {
    [j in keyof X[k]]: X[k][j] extends { c: any } ? X[k][j]['c'] : never;
  };
};

This extra check will always be true but it tells TypeScript that X[k][j] must have a property c in the true branch.

Playground


This is a bit shorter but also has the same effect:

type Y = {
  [k in keyof X]: {
    [j in keyof X[k]]: (X[k][j] & { c: any })['c'];
  };
};
  • Related