microsoft / microsoft/TypeScript

Incomplete typecheck when assigning to a mapped object type with remapped keys

Open
#60,070 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Awaiting More Feedback Suggestion
Dominant language
Go
Stars
111k
Forks
14.3k
Avg merge
2d 4h
Merged PRs (30d)
132

Description

🔎 Search Terms

typechecker, mapped object type, remapped keys, ts2322

🕗 Version & Regression Information
  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about mapped types.
    • Tried on nightly and every version down to 4.1.5 (first version supporting remapped keys)
⏯ Playground Link

https://www.typescriptlang.org/play/?#code/C4TwDgpgBAygFgQ0lAvFA3lAZgexwLigGdgAnASwDsBzAbigCMFTDKBXAWwYlPoF9aAKFDJ4SCAFkkqDNjyEA5LhwAmBfSYsoCzWv5CR0KWEgATMcjSYA2gGkoVKAGsIIHFliJkCIp-HG7AF1AwgsIIKgBQUEsNkoAY2ByHEooDiQANQQAGzYIAB57CAAPYAhKU18XNw8wgD4ACkEoFudXQlsAGmbWoi8IUP7u1rSkM0JjMzDh1vSwQf8kboBKDB6W+JSSUZMIU1tXGTnrasChEc3KbYA3HLyZPvET1zP1nbNrObMDkECZW9yECEfCAA

💻 Code
type Shape = { foo: string; bar: number; };
type ShapeMap = { foo: 'foo2'; bar: 'bar2'; };
type MappedShape = { [K in keyof Shape as ShapeMap[K]]: Shape[K] };

function mapValue<K extends keyof Shape>(
    key: K,
    shape: Shape,
    mapped: MappedShape,
    map: ShapeMap,
) {
    const mappedKey = map[key];
    const value = shape[key];
    mapped[mappedKey] = value; // <-- Not allowed to assign `value` here
}
🙁 Actual behavior

The error says

Type 'Shape[K]' is not assignable to type 'MappedShape[ShapeMap[K]]'.
  Type 'Shape' is missing the following properties from type 'MappedShape': foo2, bar2

The second line is correct, Shape is different from MappedShape since they don't have any property names in common (which is the idea 🙂). That incompatibility is not relevant when it's the value in Shape[K] that should be assignable to MappedShape[ShapeMap[K]].

To an uninitiated eye it looks like the typechecking either ends too early or too late since it compares the wrong types when trying to do the assignment. That's just a guess that might be incorrect so take that with all the salt you want 👍

🙂 Expected behavior

Assigning Shape[K] to MappedShape[ShapeMap[K]] should be allowed since they are the same types when resolved.

Additional information about the issue

If changing the code to always take foo as the key (Playground) it works correctly:

type Shape = { foo: string; bar: number; };
type ShapeMap = { foo: 'foo2'; bar: 'bar2'; };
type MappedShape = { [K in keyof Shape as ShapeMap[K]]: Shape[K] };

function mapValue(
    key: 'foo',
    shape: Shape,
    mapped: MappedShape,
    map: ShapeMap,
) {
    const mappedKey = map[key];
    const value = shape[key];
    mapped[mappedKey] = value; // No type error
}

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the behavior in the linked TypeScript Playground, focusing on the generic mapValue example and its mapped type with remapped keys. Compare it with the working key: 'foo' variant; done means the generic assignment is accepted while preserving the expected Shape[K] and MappedShape[ShapeMap[K]] relationship.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.