Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

.safeExhaustive #218

Open
jjhiggz opened this issue Jan 27, 2024 · 2 comments
Open

.safeExhaustive #218

jjhiggz opened this issue Jan 27, 2024 · 2 comments
Labels
enhancement New feature or request

Comments

@jjhiggz
Copy link

jjhiggz commented Jan 27, 2024

Is your feature request related to a problem? Please describe.

In my app that I'm working on, I love the developer experience of exhaustive checks, because they force me to handle all of the edge cases that I need. But too often I am encountering scenarios where something doesn't migrate quite right, my runtime type becomes slightly different than my compile time type, and then I get a production error and have to switch from exhaustive to otherwise.

Describe the solution you'd like

It would be extremely awesome if there was a safer alternative to .exhaustive that provided the same developer experience in typescript. To me this would look something like this:

type MyUnion = "a" | "b"

const a = "" as MyUnion

match(a)
  .with(("a") => "you chose a")
  .with(("b") => "you chose b")
  .safeExhaustive(
     "a" // <= default  if error is thrown by patern match,
     console.error // a callback that allows us to handle the error throw by pattern matching
  )

Describe alternatives you've considered
Using .otherwise

In a perfect world (I know this is probably a bigger ask), it would be cool if we could create a customized instance of match so we wouldn't have to dump in a callback every time or something like that. But I imagine that's a much bigger lift than just building a .safeExhaustive method

@jjhiggz jjhiggz added the enhancement New feature or request label Jan 27, 2024
@Liam-Tait
Copy link

Liam-Tait commented Feb 21, 2024

Similar to #144. This would cover my issue.

@kael-shipman
Copy link

kael-shipman commented Nov 4, 2024

I'm interested in this too. My proposal: Leave exhaustive exactly as it is, but allow me to pass an optional error handler that receives the error and the object. The return type of that handler adds to the options of return type if passed. For example:

const whatHappened = match(input)
  .with("a", () => "you chose a")
  .with("b", () => "you chose b")
  .exhaustive((e, obj) => {
    // obj === input
    // e === NonExhaustiveError
    console.log(e);
    return `I'm not sure what you chose :shrug:. Obj: ${JSON.stringify(obj)}`;
  });

This would allow for things like returnType() to continue to enforce the type intuitively and for exhaustive to continue to produce a useful type error just as it currently does, but would allow us to catch that error more easily at runtime. It's the equivalent of using try/catch, but much nicer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants