0

I have code that resembles this

I created custom subscript to do the unwrapping for me to make things easier.

enum MyEnum {
   case one
   case two
   case three
}

struct MyStruct {
   static var empty: Self {
       return .init()
   }

   //Some Variables Here
}

class MyClass {
   var index = 0

   var data: [MyEnum: MyStruct] = [
       .two: .empty,
       .three: .empty,
       .one: .empty
   ]

   var allTypes: [MyEnum] {
       switch Bool.random() {
           case true:
               return [.two, .three]
           case false:
               return [.one]
       }
   }

   var currentSelectedType: MyEnum {
       return allTypes[index]
   }

   func myMethod(type: MyEnum) {
       let one: MyStruct = data[type]!
       let two: MyStruct = data[currentSelectedType]!
       let three: MyStruct = data[allTypes[index]]
       let four: MyStruct = data[.one]

   }
}

fileprivate extension Dictionary {
   subscript(_ key: Key) -> Value where Key == MyEnum, Value == MyStruct {
       get {
           return self[key]!
       }
       set {
           self[key] = newValue
       }
   }
}

in my MyClass myMethod why I have to forcely unwrapp one and two but not three and four otherwise I get a compile time error

       let one: MyStruct = data[type] // Error Value of optional type 'MyStruct?' must be unwrapped to a value of type 'MyStruct'
       let two: MyStruct = data[currentSelectedType] //Error Value of optional type 'MyStruct?' must be unwrapped to a value of type 'MyStruct'

Is there something I'm missing here?

2
  • 1
    Dictionary.subscript is declared to return an optional. End of story. The compiler doesn't care what's inside the dictionary. Commented Jul 26, 2021 at 5:53
  • "why I have to forcely unwrapp one" Do you, really? Have you ever heard of unwrapping an optional value safely? Commented Jul 26, 2021 at 6:12

1 Answer 1

1

I don't have an answer on why compiler isn't picking the expected overload in this situation.

I would recommend clarifying the overload you wish to use at call site, like following.

fileprivate extension Dictionary {
    subscript(safe key: Key, defaultValue: Value = .empty) -> Value where Key == MyEnum, Value == MyStruct {
        get { return self[key, default: defaultValue] }
        set { self[key] = newValue }
    }
}

With above, you can tell compiler explicitly to use your preferred overload.

func myMethod(type: MyEnum) {
    let one: MyStruct = data[safe: type]
    let two: MyStruct = data[safe: currentSelectedType]
    let three: MyStruct = data[safe: allTypes[index]]
    let four: MyStruct = data[safe: .one]
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.