Currently, union types are kept as union types, with their constituent parts recursively merged. This is pretty much the best you could hope to do, although there are a few things you can do:
- Distribute intersections over unions
- Extract the "greatest common denominator" from the union
The first example means, for example, {a: any} & ({b: any} | {c: any})
-> {a: any, b: any} | {a: any, c: any}
. The second is the exact reverse of this.
The most useful is probably the second, i.e., extracting the common factors out of the union, since this leaves the union members as small as possible.
The problem of finding a gcd out of some objects, however, is kind of non-trivial, because there is some serious requisite recursive logic. For example:
type t =
|{
a: any,
b: {
x: any,
y: any,
}
}
|{
c: any,
b: {
y: any,
z: any
}
}
would need to be converted to:
type t =
{
b: {
y: any
}
} & (
|{
a: any,
b: {
x: any
}
}
|{
c: any,
b: {
z: any
}
}
)
The recursive logic is manageable, however the problem really here is type comparison. For example, in the above example, we have to determine that b.y
is equal in every element of the union. And I'm not sure whether it's possible to compare types like this using only externally exported methods from the typeChecker
.
enhancement help wanted api