Match.tag on union of unions

I have something like that:
type E1 = 'A' | 'B' | 'C'
type E2 = 'D' | 'E' | 'F'
type E3 = 'G' | 'H' | 'I'

type Example = {
  _tag: E1,
  where: 'A~C'
  aNumber?: never
} | {
  _tag: E2,
  where: 'D~F'
  aNumber: number
} | {
  _tag: E3,
  where: 'G~I'
  aString: string
}

declare const example: Example 

Match.value(example).pipe(
  Match.tag('A', () => 1),
  Match.tag('B', () => 2),
  Match.tag('C', () => 3),
  Match.tag('D', () => 4),
  Match.tag('E', () => 5),
  Match.tag('F', () => 6),
  Match.tag('G', () => 7),
  Match.tag('H', () => 8),
  Match.tag('I', (x) => 9), // x: never
  Match.exhaustive // error
)

Match.value(example).pipe(
  Match.when({_tag: 'A'}, () => 1),
  Match.when({_tag: 'B'}, () => 2),
  Match.when({_tag: 'C'}, () => 3),
  Match.when({_tag: 'D'}, () => 4),
  Match.when({_tag: 'E'}, () => 5),
  Match.when({_tag: 'F'}, () => 6),
  Match.when({_tag: 'G'}, () => 7),
  Match.when({_tag: 'H'}, () => 8),
  Match.when({_tag: 'I'}, (x) => 9), // (parameter) x: {
                                     //   _tag: "I";
                                     //   where: "G~I";
                                     //   aString: string;
                                     // }
  Match.exhaustive // works as expected
)

When I have unions that have _tag that can be unions or derived from unions, the Match.tag behave differently from Match.when maybe it's an uncommon use-case but I was wondering why and if it's something that could be consistent.
I know I can use Match.when with Match.is in combo, but the Match.tag is so much better ❤️
Was this page helpful?