Typically, union type order doesn’t matter. But for a typing like
type A = { isFoo: true, foo: number }
type B = { isBar: true, bar: number }
type C = [A] | [B] | [A & B]
type D = [A & B] | [B] | [A]
the order matters because the error message on invalid type will be quite different for type C and type D.
For instance,
const c: C = [{ isFoo: true, foo: 1, isBar:true }]
will have error message of Object literal may only specify known properties, and 'isBar' does not exist in type 'A'.
but
const d: D = [{ isFoo: true, foo: 1, isBar:true }]
will have ts error of Property 'bar' is missing in type '{ isFoo: true; foo: number; isBar: true; }' but required in type 'B'
which is more user friendly.
(Try on the playground)
I have tried some options like
type Reverse<T, R = never, O = T> = [T] extends [never] ? R : T extends infer U ? Reverse<Exclude<O, U>, U | R> : never;
type E = Reverse<C>
but the type of E
is still in the same order as C
.
I am at a loss if this is possible at all.
2