KeyPath<T, U?> required, but I only have KeyPath<T, U>

keypaths
optional

(Tomáš Znamenáček) #1

What are my options when a KeyPath<T, U?> is required, but I “only” have KeyPath<T, U>?

struct Foo {
    let bar: String
}

let path: KeyPath<Foo, String?> = \Foo.bar // doesn’t compile

It’s similar with getters (when T -> U? is required, but I only have T -> U), but that can be reasonably solved with a trivial “adapter” that turns U into U?. Is there a similar reasonable shortcut for key paths, other than:

extension Foo {
    var optionalBar: String? {
        return bar
    }
}

let path: KeyPath<Foo, String?> = \Foo.optionalBar

Would it make sense if I could assign KeyPath<T, U> to KeyPath<T, U?> the same way I can now assign Array<T> into Array<T?>?


(Adrian Zubarev) #2

I don't have a better answer to the question as you already showed in the second code snippet but I wonder if we could extend key-paths with functions like mapValue and compactMapValue which would operate on Value and transform the value to the generic type of the function.

let path = \Foo.bar
let mappedPath = path.mapValue { Optional($0) } // escaping a `Value -> Value?` closure for transformation during extraction of the value 

let value = foo[keyPath: mappedPath] // will extract `String` and then map it into `String?` with the above closure

@Joe_Groff what do you think?


(Tomáš Znamenáček) #3

Yes, it would be nice for key paths to play better with other language features, related thread.