0

I have a situation like so:

protocol Vehicle {} struct Car: Vehicle, Decodable {} func doSomethingWith<T>(type: T.Type) { if let vehicle = type as? Vehicle.Type { print("Nice, I detected that my type was a vehicle: \(vehicle)") } else { print("Ah, my type is a vehicle wrapped in an optional! \(type)") } } 

and I call it with:

doSomethingWith(type: Car.self) doSomethingWith(type: Car?.self) 

It will output:

Nice, I detected that my type was a vehicle: Car Ah, my type is a vehicle wrapped in an optional! Optional<Car> 

This is surprising to me. I would expect let vehicle = type as? Vehicle.Type to work in both calls to doSomethingWith, but because the second call passes an optional, my doSomethingWith function is unable to determine that this type conforms to Vehicle protocol. It makes sense, since the Optional class doesn't conform to it, the wrapped element in my optional does.

Is there some way I can modify doSomethingWith to (optionally) extract the inner type if an optional is passed to it such as in my second example?

1
  • 2
    This sounds a little like an XY problem. Can you explain why you want to do this? Commented Jul 14, 2021 at 0:22

1 Answer 1

2

Not sure what you trying to achieve but instead of passing the Vehicle type you should just create a generic type, constrain it to Vehicle type, accept an optional parameter and switch its instance. Something like:


protocol Vehicle {} struct Car: Vehicle, Decodable { let name: String } struct Truck: Vehicle, Decodable { let name: String } 

func doSomethingWith<T: Vehicle>(vehicle: T?) { switch vehicle { case let car as Car: print(car.name + " is a car") case let truck as Truck: print(truck.name + " is a truck") default: print("none of the above") } } 

let optionalCar: Car? = Car(name: "Ferrari") let truck = Truck(name: "Peterbilt") doSomethingWith(vehicle: optionalCar) doSomethingWith(vehicle: truck) 

This will print:

Ferrari is a car
Peterbilt is a truck

Sign up to request clarification or add additional context in comments.

2 Comments

I think this is clean and a great approach, but I guess what I'm really asking is why can't I do either if let vehicle = type as? Vehicle.Type or if let vehicle = type as? Optional<Vehicle>.Type to cast my Optional<Car>.Type into an Optional<Vehicle>.Type? I would've thought it would work since Car conforms to Vehicle.
@dontforget Car conforms to Vehicle. Optional<Car> doesn't

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.