Make all properties of union types accessible in TypeScript

Given a union of several interfaces I was looking for a simple way to access all possible properties.

fluidsonic
Widgetlabs Engineering

--

Problem

Usually you’ll have to narrow down the type first in order to access a property that is not present on all union members.

In the following example the property b is not accessible because it’s only defined on Foo but not on Bar:

What I was looking for instead is a type where b is an optional property because that’s what it is — optional.

Idea

Hypothetically it should work like in the following case, where a union-like type has an optional property b instead of requiring type discrimination:

Because b is defined on one of the union’s members it should be accessible, even if it’s undefined in some cases.

Merge<Foo | Bar> should basically be identical to the following interface:

Solution

I came up with the following solution after a lot of digging into the type system. A nice snippet for converting a union likeFoo | Bar into an intersection Foo & Bar also came in handy.

For each member of a union, an object type is defined that has all the properties of that member—so as usual. But for all properties from other members that are missing in this one it adds an additional optional property.

In the example above Foo would get an additional property b?: never. After forming the union with Bar this results in the merged property b?: never | string or shortened just b?: string.

Try it!

Run the complete example in TypeScript Playground.

Toughts?

Is this helpful for you? Is there a simpler way to achieve the same?

Let me know!

--

--

fluidsonic
Widgetlabs Engineering

❤️ tech / startups / crypto / travel 🛠 building https://genki.world 🏳️‍🌈 hell yes world residents