Skip to content

Instantly share code, notes, and snippets.

@nicklockwood
Last active August 17, 2017 06:56
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save nicklockwood/8abb014e00227554b653f7f466514d17 to your computer and use it in GitHub Desktop.
Save nicklockwood/8abb014e00227554b653f7f466514d17 to your computer and use it in GitHub Desktop.
Typed error use-case example
enum ValueError: Error {
case notFound
case typeMismatch
}
struct PropertyError: Error {
let name: String
let error: ValueError
}
struct ClassError: Error {
let name: String
let error: PropertyError
}
class Foo {
private func validateValue(_ value: Any) throws { // throws ValueError
... some logic
throw ValueError.typeMismatch
}
private func validateProperty(name: String, value: Any) throws { // should only throw a PropertyError
if ... {
throw PropertyError(name: name, error: .notFound)
}
try validateValue(value) // Whoops, I forgot to wrap this, now the property name is lost
}
func validate(name: String) throws { // should only throw a ClassError
do {
for (name, value) in self.properties {
try validateProperty(name: name, value: value)
}
} catch let error as PropertyError {
throw ClassError(name: name, error: error)
}
// Uh oh. Because of the bug earlier the ValueError falls through. It still gets passed
// to the caller, but now all they know is that there was a typeMismatch or notFound error
// - they've no idea which property or class it relates to.
// And note that having an explicit catch-all wouldn't help here either, because I'd still
// only have the ValueError - I wouldn't be able to convert it to the PropertyError that I
// need because I don't know which property failed validation.
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment