Exhaustiveness checking?
See original GitHub issueVery 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:
- Created 3 years ago
- Reactions:2
- Comments:5 (5 by maintainers)
Top 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 >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
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:
So I guess the only plausible way to go is just to disable it altogether in non trivial cases.
👋 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:
This block will not compile, because
2
's inferred type turns out to benumber
, so the second.with
will haveExclude<number, number>
which evaluates tonever
as narrowed input type and which isn’t compatible with a3
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
asconst
orreadonly
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.