suchipi/safety-match

Match multiple patterns simultaneously

Opened this issue · 6 comments

TmLev commented

Hi!

Thanks for this useful package.

I was wondering whether it is possible to match multiple patterns simultaneously? Like so:

const LoadState = makeTaggedUnion({
  Unstarted: none,
  Loading: (percentLoaded: number) => percentLoaded,
  Loaded: (response: Buffer) => response,
  Error: (error: Error) => error,
});

type LoadState = MemberType<typeof LoadState>;

const state: LoadState = LoadState.Unstarted;

console.log("State is ", state.match({
  Unstarted | Error: () => "unavailable", // `Unstarted` AND `Error` simultaneously.
  _: () => "available", 
}));

I'm assuming it's not possible since it requires changes to how TypeScript treats Something | AnotherThing syntax, but maybe I'm wrong.

Supporting a string key of "Unstarted | Error" is theoretically possible, since you can do some seriously wacky things with TypeScript, but it would be way too complicated for me to want to do :p

While it's not ideal, this is what I do for handling multiple cases:

// definition of LoadState and state omitted; they'd be the same as in your issue description

const unavailable = () => "unavailable";

console.log("State is ", state.match({
  Unstarted: unavailable,
  Error: unavailable,
  _: () => "available", 
}));

For something small like "unavailable" it looks silly, but when the match handler in question is larger, it makes more sense.

TmLev commented

Seems reasonable albeit not very ergonomic. Thought about doing it this way, also. Thanks!

@suchipi If I, or anyone else for that matter, would offer you a PR that makes this feature possible, would you accept it?

Yes, provided it was of good quality and etc

Reopening to better communicate that interest

I don't know how much I like the suggested approach with "Unstarted" | Error, but the idea is really cool.

You might need something like PickAll and KeyOf from here to maintain type inference.