Swift 6.0 lets a function declare which error type it throws: throws(FooError). The compiler
then types error in the catch block, so you switch over cases exhaustively instead of casting.
Declare the thrown type
Write the error type in parentheses after throws. Inside the function, throw .case works
because the compiler knows the type.
enum FooError: Error {
case tooBig
case tooSmall
}
func foo() throws(FooError) -> Int {
let value = Int.random(in: 1...100)
guard value < 60 else { throw .tooBig }
guard value > 20 else { throw .tooSmall }
return value
}
Catch without casting
Before typed throws, the caller had to catch let error as FooError and still keep a
general catch for the type-erased case. With a typed throw, one catch block gets a typed
error and a plain switch covers every case.
do {
let value = try foo()
print(value)
} catch {
switch error {
case .tooBig: print("Too big")
case .tooSmall: print("Too small")
}
}
Compatibility with untyped throws
Typed throws are optional. The compiler treats the old spellings as sugar for typed ones:
func foo() throws { } // becomes throws(any Error)
func foo() { } // becomes throws(Never)
A plain throws is throws(any Error), and a nonthrowing function is throws(Never). Existing
code keeps compiling under Swift 6.0 unchanged.