Repository navigation
Assignment fails for types with conditional lookup for a union of a generic #32816
Copy link
Copy link
Closed
Labels
DuplicateAn existing issue was already createdAn existing issue was already created
Description
TypeScript Version: Version 3.6.0-dev.20190810
Search Terms: union conditional lookup
Code
type Target<T> = T extends null ? null : T;
type Target2<T> = { "one": null, "two": T }[T extends null ? "one" : "two"];
type Target3<T> = [null, T][T extends null ? 0 : 1];
function tst<T extends string>() {
// These two pass as expected:
const case0: Target2<T | null> = 1 as any as Target2<T | null>;
const case1: { prop: Target<T | null> } = 1 as any as { prop: Target<T | null> };
const case2: { prop: Target2<T> } = 1 as any as { prop: Target2<T> };
const case3: { prop: Target3<T> } = 1 as any as { prop: Target3<T> };
// These two fail as expected:
const case4: { prop: Target2<T> } = 1 as any as { prop: Target2<T | null> };
const case5: { prop: Target3<T> } = 1 as any as { prop: Target3<T | null> };
// These two are expected to pass, but fail:
const case6: { prop: Target2<T | null> } = 1 as any as { prop: Target2<T | null> };
const case7: { prop: Target3<T | null> } = 1 as any as { prop: Target3<T | null> };
}Expected behavior:
Expected cases 6 and 7 to pass, as both sides of assignment supposed to be structurally identical.
Actual behavior:
Cases 6 and 7 fail. Example output:
error TS2719: Type '{ prop: { "one": null; "two": T | null; }["one" | (T extends null ? "one" : "two")]; }' is not assignable to type '{ prop: { "one": null; "two": T | null; }["one" | (T extends null ? "one" : "two")]; }'. Two different types with this name exist, but they are unrelated.
Types of property 'prop' are incompatible.
Type '{ "one": null; "two": T | null; }[T extends null ? "one" : "two"] | null' is not assignable to type 'null & { "one": null; "two": T | null; }[T extends null ? "one" : "two"]'.
Type '{ "one": null; "two": T | null; }[T extends null ? "one" : "two"]' is not assignable to type 'null & { "one": null; "two": T | null; }[T extends null ? "one" : "two"]'.
Type 'T | null' is not assignable to type 'null & { "one": null; "two": T | null; }[T extends null ? "one" : "two"]'.
Type 'T' is not assignable to type 'null & { "one": null; "two": T | null; }[T extends null ? "one" : "two"]'.
Type 'string' is not assignable to type 'null & { "one": null; "two": T | null; }[T extends null ? "one" : "two"]'.
Type 'string' is not assignable to type 'null'.
Type 'T' is not assignable to type 'null'.
Type '{ "one": null; "two": T | null; }[T extends null ? "one" : "two"]' is not assignable to type 'null'.
Type 'T | null' is not assignable to type 'null'.
Type 'T' is not assignable to type 'null'.
Type 'string' is not assignable to type 'null'.
Related Issues: #30152 looks similar
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
DuplicateAn existing issue was already createdAn existing issue was already created
Activity
AnyhowStep commentedon Aug 12, 2019
Feels a little bit like this #32442
Except yours does not use function params.
jack-williams commentedon Aug 12, 2019
This is a consequence of #30769 and fundamentally the same issue as discussed in #31833, however the trigger is slightly different.
The instantiation of the distributive conditional type
T extends null ? "one" : "two"is"one" | (T extends null ? "one" : "two")as the conditional distributes over the union. The union key causes the index access type in the target type to simplify to an intersection (despite the property never being assigned), as per #30769.typescript-bot commentedon Aug 19, 2019
This issue has been marked as a 'Duplicate' and has seen no recent activity. It has been automatically closed for house-keeping purposes.