Skip to content

Type alias name (union) is not preserved when using index access/lookup types #32287

@OliverJAsh

Description

@OliverJAsh

TypeScript Version: 3.5.2

Search Terms: indexed access lookup types type alias naming

Code

Given:

type MyUnion = 1 | 2 | 3;

// Hover this
type MyObject = { value: MyUnion };

If I hover over MyObject, I see { value: MyUnion; }.

However, given:

type MyRecord = {
    Foo: 1;
    Bar: 2;
    Baz: 3;
}

type MyUnion = MyRecord[keyof MyRecord];

// Hover this
type MyObject = { value: MyUnion };

If I hover over MyObject, I see { value: 1 | 2 | 3; }.

I would expect the same behaviour as we see in my first example ({ value: MyUnion; }). The name of the type alias, MyUnion, should be preserved and its usage/reference inside of MyObject should be shown.

To give some context on my real world use case for this: I am using Unionize to create tagged unions (to avoid boilerplate for constructors, matchers, and type predicates). However, because of the issue described above, the types become very difficult to inspect/read: pelotom/unionize#60.

Under the hood, Unionize does something like this:

type Foo = { foo: number };
type Bar = { bar: number };
type Baz = { baz: number };

type MyUnionRecord = {
    Foo: Foo;
    Bar: Bar;
    Baz: Baz;
};

type MyUnionTaggedRecord = { [K in keyof MyUnionRecord]: { tag: K; value: MyUnionRecord[K] } };
type MyUnion = MyUnionTaggedRecord[keyof MyUnionTaggedRecord];

// Hover this
type MyObject = { value: MyUnion };

If we hover over MyObject here, we see:

{
    value: {
        tag: "Foo";
        value: Foo;
    } | {
        tag: "Bar";
        value: Bar;
    } | {
        tag: "Baz";
        value: Baz;
    };
}

… when we really want to see { value: MyUnion }.

As I demonstrated in pelotom/unionize#60, this scales really badly, e.g. when nesting unions.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Needs ProposalThis issue needs a plan that clarifies the finer details of how it could be implemented.SuggestionAn idea for TypeScript

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions