Home > Enterprise >  How to I cast a type to a variable in an enum within a switch statement?
How to I cast a type to a variable in an enum within a switch statement?

Time:10-10

switch error {
case Project.Client.LoadError.operationFailed(let error2):
    switch error2 {
    case Project.Client.APIClientError.invalidStatusCode(let message, _):
        guard message != nil, message == "error" else {
            return refresh()
        }
        delegate?.error(invalidScript)
    default:
        refresh()
    }
default:
    refresh()
}

Here is my current code. This works but I feel there is a better way to do this. How can I make error2 NOT go through another switch statement and just cast it as an invalidStatusCode that I can use?

Or, what terms can I search up to better understand what is happening here/understand what to look up myself for the answer? As I might not be fully understanding switch statements as casting type.

Thank you in advance.

CodePudding user response:

Pattern matching of enums with associated values is composable, so you can do this:

switch error {
case Project.Client.LoadError.operationFailed(Project.Client.APIClientError.invalidStatusCode("error" , _)):
    delegate?.error(invalidScript)
default:
    refresh()
}

You might notice that this is a bit hard to read because of how long these fully-qualified type-names are.

I suspect the type of error is the general Error, but in other cases, if the type of error is already-known to be Project.Client.LoadError, then you can just use .operationFailed (leaving the type to be inferred from context). And if .operationFailed's associated type is known to have type Project.Client.APIClientError, you can just use .invalidStatusCode.

If not, you can use some local type-aliases can help with that:

typealias LoadError = Project.Client.LoadError
typealias APIClientError = Project.Client.APIClientError

switch error {
case LoadError.operationFailed(APIClientError.invalidStatusCode("error", _)):
    delegate?.error(invalidScript)
default:
    refresh()
}

CodePudding user response:

Since you are just drilling down to one case for both switches, you don't need any switches at all. You can use if case instead. To generalize, suppose we have this:

enum Outer {
    case inner(Inner)
    case other
}

enum Inner {
    case message(String)
    case other
}

Now suppose subject might be an Outer. Then to determine that this is an Outer's .inner case whose Inner value is .message and that message's value is "howdy", we can say:

if case Outer.inner(let inner) = subject, 
    case Inner.message(let message) = inner, 
    message == "howdy" {
  • Related