-
-
Notifications
You must be signed in to change notification settings - Fork 138
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
Allow otherwise to chain onto exhaustive #144
Comments
Hey! I think I'd use |
Im kind of confused about this use-case. In what context would you have a scenario that matches your example of
? |
Wrapping the expressions in const value = match(unit)
.with('days', () => 'd')
.with('hours', () => 'h')
.exhaustiveOtherwise(() => 'never') vs let value: string
try {
value = match(unit)
.with("days", () => "d")
.with("hours", () => "h")
.exhaustive()
} catch (error) {
value = "never"
} What I am working with is not an ideal case, the application has partially transitioned to TypeScript. Some types are only partially correct right now. Adding a catch or otherwise that works with exhaustive means I can start taking advantage of exhaustiveness checking, while preventing errors at runtime while types cannot be fully trusted. Maybe the ideal approach is to have everything be I don't know if this is possible, but having a const unit: 'days' | 'hours' | unknown;
const value = match(unit)
.with("days", () => "d")
.with("hours", () => "h")
.with(P.unknown, () => 'never')
.exhaustive() I want to be able to:
One of the situations I have is where data is persisted in local storage and loaded back in without any validation, the types "should" be the same, but can be different based on an old stored version, renaming, user changing etc |
How about just adding an optional argument to declare const input: 'a' | 'b';
const mode = match(input)
.with('a', () => Mode.A)
.with('b', () => Mode.B)
.exhaustive(() => Mode.Fallback) In addition to that, it'd be better to have the value passed to the callback as declare const input: 'a' | 'b';
const mode = match(input)
.with('a', () => Mode.A)
.with('b', () => Mode.B)
.exhaustive(v => {
throw new ValidationError(`Unknown mode identifier: ${v}`)
}) |
I dunno it looks to me like there's a fundamental disagreement about what "exhaustive" means in this context. In my opinion "exhaustive" loses it's meaning if it can be used in a scenario where you need a fall back Also, as I understand it there is a performance cost to using exhaustive, so I think it's purpose is pretty narrowly defined. If you're getting input that you can't type narrow into exhaustive checks then I think there's a strong case to be made that it would be inappropriate to use exhaustive from a conceptual as well as a performance standpoint. |
@gvergnaud are you open to PRs regarding this? Ref #38 Like oguimbal said:
|
Could use a try catch but I prefer not to. Here is a workaround (kind of) import { P, match } from 'ts-pattern'
type Status = 'active' | 'inactive' | 'pending'
const status = 'active' as Status
match(status)
.with('active', () => '...')
.with('inactive', () => '...')
// .with('pending', () => '...')
// ^ uncomment resolve NonExhaustiveError
.with(P.not({}), () => 'fallback')
.exhaustive()
// ~~~~~~~~~~ This expression is not callable.
// Type 'NonExhaustiveError<"pending">' has no call signatures. |
Taking inspiration from Effect's declare const unit: string
match(unit)
.with('days', () => 'd')
.with('hours', () => 'h')
.otherwiseAbsurd() // Equivalent to `.otherwise(() => { throw new Error('Absurd!') })` I think it's much easier to grasp than the other options presented in this issue. |
Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
We have types, however they are not completely safe. I'd like to be able to ensure the exhaustive type check is run for case such as union where we want to handle where , but they also run an otherwise to prevent throwing of an error.
This means we can have the type checking where a type is partially complete.
Describe the solution you'd like
A clear and concise description of what you want to happen.
Add a new method
exhaustiveOtherwise
which does the exhaustive type check with a otherwisehandler
Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.
Allow
otherwise
to chain onto the end ofexhaustive
Add validation such as zod to the data to handle incorrect data (hard as I would like to transition new code to be type safe without having to re-write all types)
Additional context
Add any other context or screenshots about the feature request here.
The text was updated successfully, but these errors were encountered: