Skip to content

Obscure "type cannot be used to index type" error when a mapped type is nested into another mapped type #54289

Closed as not planned
@shau-kote

Description

@shau-kote

Bug Report

🔎 Search Terms

  • mapped type
  • nested mapped type

🕗 Version & Regression Information

  • It reproduces in TS of versions from 3.8.3 to 5.0.4 (there are other compiler errors in earlier versions).
  • It reproduces in Nightly (v5.2.0-dev.20230516) as well.
  • I failed to find out a description of similar cases in the FAQ.

⏯ Playground Link

Playground link with relevant code

💻 Code

type Values<T extends object> = T[keyof T]

const ENTITY_CONFIG = {
  'entity1': {
    'step1':  {
      body: { aaa: 1 }
    },
    'step2':  {
      body: { bbb: 1 }
    },
  },
  'entity2': {
    'step1':  {
      body: { ccc: 1 }
    },
    'step2':  {
      body: { ddd: 1 }
    },
  }
} as const

type EntityConfig = typeof ENTITY_CONFIG

type EntityType = Values<{
  [T in keyof EntityConfig]: {
    entityName: T,

    step: Values<{
      [S in keyof EntityConfig[T]]: {
        stepName: S
        body: EntityConfig[T][S]['body'] // <-- TS2536 error
      }
    }>
  }
}>

🙁 Actual behavior

I see an error around the EntityConfig[T][S]['body'] type expression with the following error message: Type '"body"' cannot be used to index type '{ readonly entity1: { readonly step1: { readonly body: { readonly aaa: 1; }; }; readonly step2: { readonly body: { readonly bbb: 1; }; }; }; readonly entity2: { readonly step1: { readonly body: { readonly ccc: 1; }; }; readonly step2: { ...; }; }; }[T][S]'..

Firstly, I don't expect any errors in my type definition. Although it's possible of course that my mental model is wrong, or I don't understand some compiler limitations.

Secondly, the error message is quite obscure to me, it doesn't help to understand what I do wrong and how to fix it.

🙂 Expected behavior

I expect that the EntityType will be successfully constructed and will be something like this:

type EntityType = {
  entityName: 'entity1'
  step: {
    stepName: 'step1'
    body: { aaa: 1 }
  } | {
    stepName: 'step2'
    body: { bbb: 1 }
  }
} | {
  entityName: 'entity2'
  step: {
    stepName: 'step1'
    body: { ccc: 1 }
  } | {
    stepName: 'step2'
    body: { ddd: 1 }
  }
}

In fact, it seems to me based on my "tests" in the playground above that the EntityType type construction works well, despite the error in the type definition.

Metadata

Metadata

Assignees

No one assigned

    Labels

    DuplicateAn existing issue was already created

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions