-
Notifications
You must be signed in to change notification settings - Fork 13.1k
Closed
Labels
Design LimitationConstraints of the existing architecture prevent this from being fixedConstraints of the existing architecture prevent this from being fixedFixedA PR has been merged for this issueA PR has been merged for this issue
Description
TypeScript Version: 2.3.2
Summary: Tagged<Opts>[keyof Opts] evaluates differently depending on whether Opts is a type alias or a type parameter.
Code
// Given an index type:
type MyOpts = {
x: number,
y: string,
};
// pair each value with its index tag:
type Tagged<T> = { [K in keyof T]: { tag: K, val: T[K] } };
// which produces:
// Tagged<MyOpts> == {
// x: { tag: 'x', val: number },
// y: { tag: 'y', val: string }
// }
// Then project the signature of that mapped type to get a tagged/disjoint union:
type MyTaggedUnion1 = Tagged<MyOpts>[keyof MyOpts];
// which produces:
// MyTaggedUnion1 = { tag: 'x', val: number } | { tag: 'y', val: string }
// which is exactly what we want.
// But when trying to express Tagged<MyOpts>[keyof MyOpts] as a generic type expression,
// the result turns out to be not as specific:
type TaggedUnion<Opts> = Tagged<Opts>[keyof Opts];
type MyTaggedUnion2 = TaggedUnion<MyOpts>;
// produces:
// MyTaggedUnion2 = { tag: 'x' | 'y', val: number | string }Expected behavior:
Tagged<O>[keyof O] should produce the same thing, whether O is an alias to a type literal or the name of a type parameter.
Actual behavior:
The literal version produces the desirable result:
{ tag: 'x', val: number } | { tag: 'y', val: string }The parameterized version produces the weaker result:
{ tag: 'x' | 'y', val: number | string }
Possibly related: #15983
Metadata
Metadata
Assignees
Labels
Design LimitationConstraints of the existing architecture prevent this from being fixedConstraints of the existing architecture prevent this from being fixedFixedA PR has been merged for this issueA PR has been merged for this issue