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.
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!