Skip to content

Regression: Mapped type with recursive key remapping crashes tsc with "RangeError: Maximum call stack size exceeded" in [email protected]+Β #60476

@nking07049925

Description

@nking07049925

πŸ”Ž Search Terms

"Mapped type", "Recursive mapped type", "Recursive type", "RangeError: maximum call stack size exceeded"

πŸ•— Version & Regression Information

  • This changed between versions 5.3.3 and 5.4.5

⏯ Playground Link

https://www.typescriptlang.org/play/?ts=5.4.5#code/KYDwDg9gTgLgBDAnmYcBiAbAhjGwB2AKssADwDKEArlAMaqh74AmAznBAEYBWwtMAGjiEsUAObAYAPjgBeOAG8AUHDgBtANLBEcAJb44Aa20QAZnEo16cLOy07GBNnFYwo+sStVwA-Bep0wJraALpwjizsXLz8Xt6+cAAGACQK9gC+AHSpxohm6Ni4BMQoFAH0wYghQiLikjIAZC5uHumJcd4AXHD2Hd34wABuwFAhALQ+3bUSMADcSunzSkgo6LrAGMzkG3zw8sqqMFicGMDdru74YvOqpuub5y1X8+lKyyRwAILMzFDArOx9l5IK4AMIQZhnZqXa5eSGsWjuMAwXQQfCPGE3Gw-P4AjEeF5vFaoACqrBGckUXl0zH6VAAtpwRlj8Fh6VCLgSvFgcf9WN1vr8+YT3qtMDgmMBmGSKfJxUUiCRSDKoEI0Pctjt+FJ5gB6XXxQ0APR8QA

πŸ’» Code

export type FlattenType<Source extends object, Target> = {
  [Key in keyof Source as Key extends string
    ? Source[Key] extends object
      ? `${Key}.${keyof FlattenType<Source[Key], Target> & string}`
      : Key
    : never]-?: Target;
};

type FieldSelect = {
  table: string;
  field: string;
}

type Address = {
  postCode: string;
  description: string;
  address: string;
}

type User = {
  id: number;
  name: string;
  address: Address;
}

type FlattenedUser = FlattenType<User, FieldSelect>;
//         ^?

πŸ™ Actual behavior

Compilation crashes with "RangeError: maximum call stack size exceeded"

πŸ™‚ Expected behavior

No crash with the type working correctly or explicit error on the recursive type like "Type instantiation is excessively deep and possibly infinite. ts(2589)"

Additional information about the issue

Same playground in version 5.3.3 where the type resolves with no crash
https://www.typescriptlang.org/play/?ts=5.3.3#code/KYDwDg9gTgLgBDAnmYcBiAbAhjGwB2AKssADwDKEArlAMaqh74AmAznBAEYBWwtMAGjiEsUAObAYAPjgBeOAG8AUHDgBtANLBEcAJb44Aa20QAZnEo16cLOy07GBNnFYwo+sStVwA-Bep0wJraALpwjizsXLz8Xt6+cAAGACQK9gC+AHSpxohm6Ni4BMQoFAH0wYghQiLikjIAZC5uHumJcd4AXHD2Hd34wABuwFAhALQ+3bUSMADcSunzSkgo6LrAGMzkG3zw8sqqMFicGMDdru74YvOqpuub5y1X8+lKyyRwAILMzFDArOx9l5IK4AMIQZhnZqXa5eSGsWjuMAwXQQfCPGE3Gw-P4AjEeF5vFaoACqrBGckUXl0zH6VAAtpwRlj8Fh6VCLgSvFgcf9WN1vr8+YT3qtMDgmMBmGSKfJxUUiCRSDKoEI0Pctjt+FJ5gB6XXxQ0APR8QA

We ran into this crash when upgrading the ts version in our project.

There's a workaround based on the approach described in https://blog.swmansion.com/deep-flatten-typescript-type-c0d123028d82 which doesn't cause a crash on these versions.

The original type that caused the crash has mostly the same motivation as the blog post above. The provided snippet was simplified to a minimal reproducible example.

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugA bug in TypeScriptHelp WantedYou can do this

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions