Skip to content

Multiple keys being remapped to same key causes unstable modifier propagation #62318

@cm-ayf

Description

@cm-ayf

🔎 Search Terms

Mapped Types, Key Remapping

🕗 Version & Regression Information

  • This has been happening since first release of key remapping at 4.1 (tested with v4.1.5 at Playground) until nightly (tested with v6.0.0-dev.20250822 at Playground).

⏯ Playground Link

https://www.typescriptlang.org/play/?#code/C4TwDgpgBAShC2BDMBpCIAqB7AkgOwEtgDEAbABUQCdgAeDAPigF4oBvAKCm6gG0UoBPFADW6LADMoGKIgDOUARAAewCHgAmCgAYASNkIkQqUAGIEqc4AF8AdPsPGoAfThXr2qAH4zFq1AAuRQBdILwAV1JSAG4Oa1iOUEhfS2AAeTBiLDwyFlgEZDRMXEJiMkoaWk4eKAB6WqgAPS8uHgAiCSwsWwAjajavIKsqIQBzWJqOrt7EAC82sPD4HuNY6wYEpOhzVLgAR3CLCA08uCRUdGx8IhIKajpqnnqmlsnO7r75xeXV1u4pj79QZQYZjNYbDhAA

💻 Code

type RemapKeyToInitialPart<T> = {
    [K in keyof T as K extends `${infer First}.${infer _Rest}` ? First : K]: null;
};

type FirstOptional = RemapKeyToInitialPart<{
    // ^?
    "foo.bar"?: string;
    "foo.baz": number;
}>;

type FirstRequired = RemapKeyToInitialPart<{
    // ^?
    "foo.baz": number;
    "foo.bar"?: string;
}>;

🙁 Actual behavior

type FirstOptional and type FirstRequired results in different types:

  • type FirstOptional has optional property foo
  • type FirstRequired has required property foo

🙂 Expected behavior

type FirstOptional and type FirstRequired results in same type. I would expect it to be same as type FirstRequired type FirstOptional.

Additional information about the issue

My motivation was to implement a utility type Expand<T> which transforms { "foo.bar": number } to { foo: { bar: number } } (playground)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions