Discriminated Unions in Typescript

Getting more out of your TS types

Take the below as a starting point.

We have an enum and an interface:

Enum and type

We can assume ’Items’ might be something like an array of strings.

We then have a function which uses these types:

Function using generics

Here we are using the generic T to describe the relationship between the ’type’ and ’payload’ in this function’s parameters, which are not static types.

However, the issue is that when we hover on ’payload’, we see this:

Hover on payload and see generic

Unfortunately, the type of ’payload’ within the switch statement remains as CollectionPayloads[T].

We would hope that TypeScript would know that ’T’ is now a specific value, in fact, one of several possibilities within CollectionPayloads.

However, TS isn’t smart enough to dig that deep - this is actually an intentionally designed feature of TS, limited for performance reasons.

Additionally, we want TS to narrow the type based on the ’case’ within the switch statement.

How can we achieve this type narrowing within the switch statement?

We can combine the type and payload into a single type:

Single union type

And reference it in the function like so:

Single union type usage in function

Now when we hover on ’payload’ we see that we get full type information:

Hover on payload showing full type info

In short, in this example, TypeScript is able to perform type narrowing because of the relationships between various combinations of potential payloads.