Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I restrict the type that a function throws in Swift?

Tags:

swift

swift3

When calling a function in Swift 3 that throws, you have to be exhaustive in catching all possible errors, which often means you have an unnecessary extra catch {} at the end to handle errors that won't happen.

Is it possible to say throws MyErrorType so that the compiler can know you have indeed been exhaustive when you handle all cases from that enumeration?

like image 514
jhabbott Avatar asked Sep 21 '16 13:09

jhabbott


People also ask

How to use throw in Swift?

To indicate that a function, method, or initializer can throw an error, you write the throws keyword in the function's declaration after its parameters. A function marked with throws is called a throwing function. If the function specifies a return type, you write the throws keyword before the return arrow ( -> ).

What does throw mean in Swift?

In Swift 2.0, Apple introduced the throws keyword in Swift. This keyword is so helpful for us on error handling. Basically throws keyword allows us to throw errors inside a method, property, class, or struct. After async/await came out with Swift 5.5, throwing functions became more popular.

How would you call a function that throws error and also returns a value Swift?

It's called rethrows . The rethrows keyword is used for functions that don't directly throw an error.


Video Answer


1 Answers

There's no simple way to be type-safe with thrown errors. Consider this, if the compiler allowed you to specify throws MyErrorType, then it would also have to ensure within that function body that you're not trying a function that could potentially throw a different type outside of a do/catch block. (Well there is but it would add layers of unnecessary complexity). The Swift compiler can already be slow and get stuck in loops when inferring types, inferring Thrown types all the way up a chain of throwing functions could be a nightmare.

The running idea is that for most errors you're going to handle them in a small subset of ways anyhow.

That being said, there's no need for you to add extra catch let error as MyErrorType clauses, you can simply use a switch in a catch block like so:

do {
  try something()
} catch let e {
  switch e {
  case let m as MyErrorType: handleMyError(m)
  case let o as OtherErrorType: handleOther(o)
  case is ThirdErrorType: print("error \(e)")
  default: handleElse(e)
  }
}
like image 54
apocolipse Avatar answered Sep 28 '22 11:09

apocolipse