Open
Description
openedon Aug 24, 2021
Bug Report
Eager mapped types result in the indexed access of an union created from all elements of a tuple resulting in the widest type in the tuple.
🔎 Search Terms
eager mapped types, array intersection filtering
🕗 Version & Regression Information
This bug exists in every version of TypeScript available on the playground with support for the necessary language features through nightly. In 3.8.3, both assignments to test
fail.
- This changed between versions 3.8.3 and 3.9.7
⏯ Playground Link
Playground link with relevant code
💻 Code
interface ListElement {
condition: boolean;
id: string;
}
const list = [
{ condition: true, id: "yes" },
{ condition: false, id: "no" },
] as const;
type CheckCondition<
List extends readonly ListElement[],
ID extends List[number]["id"],
> = ({ id: ID } & List[number])["condition"]
type Mapped = {
[ID in "yes"]: CheckCondition<typeof list, ID>
}["yes"]
type NotMapped = CheckCondition<typeof list, "yes">
declare const mapped: Mapped
declare const notMapped: NotMapped
let test: true = true
test = mapped // error, should pass
test = notMapped
🙁 Actual behavior
The type constructed using a mapped type loses specificity, becoming (typeof list)[number]["condition"]
, which in this case is true | false == boolean
🙂 Expected behavior
The mapped type should have no effect on the resulting type.
This is the result of a question on the TS discord.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment