This is something I've wanted for a long time. Here's an example from something I've been working on recently that could greatly benefit from this:
Before:
enum CommonErrorReasonCode: Int {
// Common
case unknown = -1
case networkError = 17020
case tooManyRequests = 17010
}
enum AuthErrorReasonCode: Int {
// Common
case unknown = -1
case networkError = 17020
case tooManyRequests = 17010
// Auth-related
case invalidCredential = 17004
case invalidEmail = 17008
case userDisabled = 17005
}
struct CommonError: Error {
var reasonCode: CommonErrorReasonCode
var localizedDescription: String
}
struct AuthError: Error {
var reasonCode: AuthErrorReasonCode
var localizedDescription: String
}
After:
protocol CommonErrorReasonCode {
static var unknown: Self { get }
static var networkError: Self { get }
static var tooManyRequests: Self { get }
}
protocol AuthErrorReasonCode {
static var invalidCredential: Self { get }
static var invalidEmail: Self { get }
static var userDisabled: Self { get }
}
enum ErrorReasonCode: Int, CommonErrorReasonCode, AuthErrorReasonCode {
// Common
case unknown = -1
case networkError = 17020
case tooManyRequests = 17010
// Auth-related
case invalidCredential = 17004
case invalidEmail = 17008
case userDisabled = 17005
}
struct Error<T>: Swift.Error {
var reasonCode: T
var localizedDescription: String
}
typealias CommonError = Error<CommonErrorReasonCode>
typealias AuthError = Error<CommonErrorReasonCode & AuthErrorReasonCode>
A lot easier to maintain, safer, and efficient IMO.