question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Exhaustiveness checking?

See original GitHub issue

Very cool library, thanks for creating it! Would it be possible to force exhaustiveness checking for union types? For example:

function getSomeString(unionType:  "foo" | "bar"): string{
     return match(unionType).with("foo", () => `A string result, but we won't check for "bar"!`).run()
}

This will not be a compile time error. If you write it as

function getSomeString(unionType:  "foo" | "bar"): string{
    if(unionType === "foo"){
        return `A string result, but we won't check for "bar"!`
    } 
}

You get TS2366: Function lacks ending return statement and return type does not include 'undefined' because TS can verify that you haven’t exhausted all of the cases.

It would be really nice if this library could take advantage of that. Failure to check all cases is a really easy bug to introduce!

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:2
  • Comments:5 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
oguimbalcommented, Nov 27, 2020

That’s why case guards have been removed from Elm pattern matching, if I remember right 😃 And like you said, I guess that thats why they’re not enabled by default in Haskell … it can be quite confusing:

image

So I guess the only plausible way to go is just to disable it altogether in non trivial cases.

1reaction
gvergnaudcommented, Nov 28, 2020

👋 Hey, Thanks for your feedback!

I had a go at implementing exhaustive pattern matching when I first wrote this library (Here is the branch if you are curious). I agree having exhaustive patterns would be immensely useful, but it’s actually pretty hard to get right.

Support for when predicate doesn’t make our lives easier to implement it, because if the function given isn’t a Type Guard there is no way to narrow the return type to something more precise. I think that’s why exhaustive pattern matching isn’t turned on by default on languages like Haskell.

The second issue we face is with literal patterns. Consider this case:

const input: number
match(input)
    .with(2, () => 'two')
    .with(3, () => 'three')
    .run()

This block will not compile, because 2 's inferred type turns out to be number, so the second .with will have Exclude<number, number> which evaluates to never as narrowed input type and which isn’t compatible with a 3 pattern. Of course you could do .with(2 as const, ...) to mitigate this issue, but the fact that the default behavior is incorrect and confusing discouraged me to actually push this experiment to the main branch. I looked for ways to force Typescript to consider the first argument of .with as const or readonly by default, but I didn’t find a way to make it work.

Another approach we could have would be to make exhaustive patterns an opt-in behavior by extending the API surface of the library, as @oguimbal suggested in this PR but I’d like to make sure the proposed API makes sense before merging it.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Exhaustive Type Checking with TypeScript!
In short, Exhaustive Type Checking is when your static compiler checks that you're not leaving a possibility unchecked.
Read more >
Exhaustiveness Checking with Mypy | Haki Benita
Exhaustiveness checking is a common feature of type checkers, and a very useful one! In this article I'm going to show you how...
Read more >
Exhaustiveness (T.absurd) - Sorbet
Exhaustiveness checking is a feature of a language where the type checker guarantees that the programmer has covered all cases.
Read more >
Discriminated Unions and Exhaustiveness Checking in ...
In this article, you'll find an example of what we learned about discriminated unions and exhaustiveness checking in Typescript and why it's ...
Read more >
Exhaustiveness Checking In Typescript - kimserey lam
In today's post, we'll continue to explore some of the narrowing functionalities of Typescript by looking at discriminated union narrowing and ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found