Microsoft/TypeScript

Multiple keys being remapped to same key causes unstable modifier propagation

Open

#62,318 创建于 2025年8月22日

在 GitHub 查看
 (3 评论) (0 反应) (0 负责人)TypeScript (6,726 fork)batch import
BugDomain: Mapped TypesHelp Wanted

仓库指标

Star
 (48,455 star)
PR 合并指标
 (平均合并 6天 17小时) (30 天内合并 9 个 PR)

描述

🔎 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)

贡献者指南