0

I want to make a Swift Error that describes how the Type of a variable coming from Objective-C was wrong. Here's how I tried to define the struct:

public struct UnexpectedResultTypeError<Expected, Actual>: Error {
    let expected: Expected.Type
    let actual: Actual.Type

    init(expected: Expected.Type, got actual: Actual.Type) {
        self.expected = expected
        self.actual = actual
    }
}

I figured that was fine, but now I can't initialize it:

UnexpectedResultTypeError<String, Any>(expected: String.self, got: type(of: serializedResult))
Cannot invoke initializer for type 'UnexpectedResultTypeError<String, Any>' with an argument list of type '(expected: String.Type, got: Any.Type)'
Ky -
  • 30,724
  • 51
  • 192
  • 308
  • 1
    Compare https://stackoverflow.com/q/45234233/2976878. With a generic placeholder `T`, when `T` is some protocol `P` (`Any` is treated like a protocol by the compiler), `T.Type` is *not* `P.Type`. It's `P.Protocol`, so `Any.Protocol` in your case. The only value `Any.Protocol` can hold is `Any.self`. – Hamish Jul 25 '17 at 15:56
  • Do you really need to use generic placeholders here? Is an `UnexpectedResultTypeError` *really* a completely different type to `UnexpectedResultTypeError`? I would suggest all you want is a non-generic struct with two properties of type `Any.Type`. – Hamish Jul 25 '17 at 16:00
  • @Hamish I'm more distinguishing between `Int` and `Dictionary`, here. Also, since I _expect_ something, I have no value with which to populate an `expected` field that is not a type. – Ky - Jul 25 '17 at 16:10
  • Not sure I understand you. Also given you'll be throwing this type as an `Error`, surely you'll just want to be catching an `UnexpectedResultTypeError`, rather than lots of different specialisations of it? I really don't see what you gain from using generic placeholders here. – Hamish Jul 25 '17 at 16:13
  • @Hamish I want to catch a generic error and let Swift's built-in stringification give me something like `UnexpectedResultTypeError>(expected: Swift.String, actual: Swift.Dictionary)` – Ky - Jul 25 '17 at 18:05
  • Again, I don't see why you need generics for that; metatypes already have the string description you're expecting (https://gist.github.com/hamishknight/999577d3d17f9904f008d7fc5547e743). – Hamish Jul 25 '17 at 18:11
  • @Hamish I see! That would do nicely as an answer :) – Ky - Jul 25 '17 at 18:12

0 Answers0