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

Counter proposal : type safe try/catch #43

Open
y-nk opened this issue Sep 11, 2024 · 5 comments
Open

Counter proposal : type safe try/catch #43

y-nk opened this issue Sep 11, 2024 · 5 comments

Comments

@y-nk
Copy link

y-nk commented Sep 11, 2024

The proposal seems copying Golang famous value, _ := blah() but I think we can do better in error handling if we copied dart/java instead.

Considering the 1st example:

async function getData() {
  const [requestError, response] ?= await fetch(
    "https://api.example.com/data"
  )

  if (requestError) {
    handleRequestError(requestError)
    return
  }

  const [parseError, json] ?= await response.json()

  if (parseError) {
    handleParseError(parseError)
    return
  }

  const [validationError, data] ?= validationSchema.parse(json)

  if (validationError) {
    handleValidationError(validationError)
    return
  }

  return data
}

I would rather leverage a new on XXX catch (err) instead which would look like this:

async function getData() {
  try {
    cons res = await fetch("https://api.example.com/data")

    return validationSchema.parse(
      await res.json()
    )
  }
  on RequestError catch (err) {
    handleRequestError(err)
  }
  on ParseError catch (err) {
    handleValidationError(err)
  }
  on ValidationError catch (err) {
    handleValidationError(err)
  }
  catch (err) {
    handleUnknownError(err)
  }
}

Advantages over your proposal:

  1. we can read happy path without "if error" interrupting every 2 lines
  2. the example provided does not provide type checking on the errors so you will end up with a if/else or a big switch case if you missed one or if the errors are not granular in the "below" layer (for example, try adding network error handling in fetch call and we'll see)
  3. it encourages people to throw (typed) Error instances (rather than returning strings and whatnot)
  4. try catch can provide an escape hatch like a global catch with the final catch, but this not really different from the proposal
  5. errors can still bubble up in the stack which is very powerful

EDIT: this addresses your concerns about nested try/catch

EDIT2: would consider also rethrow as a syntaxic sugar of throw err, that'd be nice but it's not really inside the proposal

@y-nk
Copy link
Author

y-nk commented Sep 12, 2024

@nicolo-ribaudo indeed it is! the syntax feels a bit odd to me because of those 2 reasons:

  1. the 1st when: would introduce colon to create a block (instead of curly braces)

  2. the 2nd e is X feels like competing with typescript use of is keyword and is more a assertion (it IS) rather than on which is similar to when

Alternatively, having:

try {
    cons res = await fetch("https://api.example.com/data")

    return validationSchema.parse(
      await res.json()
    )
  }
  when RequestError catch (err) {
    handleRequestError(err)
  }

...could also work, but idk, on feels a bit more fluent 🤷

@ljharb
Copy link

ljharb commented Sep 12, 2024

“on” is a word that’s associated with event listeners and observables; i don’t think that makes sense. The pattern matching proposal may add an is operator, which is what that would be based on. TS only uses it for predicate return syntax, which is in type space and thus irrelevant.

@y-nk
Copy link
Author

y-nk commented Sep 13, 2024

@ljharb i don't have strong opinion on it. when also suits, catch (err is X) also suits... since they both fit the underlying idea of having an internal branching based on err instanceof X.

the difference imho, is in where the keyword is located. with when Class catch (err), i think it reads easier if the type of err is X then catch because of how the words are placed. with catch (err is X) i personally see more an declaration than a if branching, but that may be only me.

@FrameMuse
Copy link

What about Python-like style

try {
    cons res = await fetch("https://api.example.com/data")

    return validationSchema.parse(
      await res.json()
    )
}
except RequestError (error) { }

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

No branches or pull requests

4 participants