Using KeyPaths in a Result Builder
Every now and then, I’ve attempted to use a KeyPath in result builders for fun and sure profit… except I’ve never managed to get short-form key path expression working.
For example, suppose we have the following simple KeyPathBuilder1 and usage:
@resultBuilder
enum KeyPathBuilder<Root> {
static func buildBlock<A>(
_ keyPath: KeyPath<Root, A>
) -> KeyPath<Root, A> {
keyPath
}
}
struct User {
let name: String
}
@KeyPathBuilder<User>
var keyPath: KeyPath<User, String> {
\.name
}
When we try to use the builder with a short-form key path, we are presented the following error for the line with \.name
:
Cannot infer key path type from context; consider explicitly specifying a root type
Swift is informing us that inference is not possible right now, so we need to add the root type to the key path:
@KeyPathBuilder<User>
var keyPath: KeyPath<User, String> {
\User.name
}
While the full form key path is indeed very explicit, it is also wordy when one considers that we probably want to do something more interesting with a builder and we have many key paths listed one after another.
Fixing the error with buildExpression
I stumbled over a solution today, and I’m not entirely sure why I even tried it if I’m honest.
static func buildExpression<A>(
_ expression: KeyPath<Root, A>
) -> KeyPath<Root, A> {
expression
}
Adding the buildExpression
function to KeyPathBuilder
will allow us to use the short-form key path expression as we originally desired! 🥳
An example project can be found on GitHub.
-
And this really is too simple for real use, but it’s the minimum viable result builder that shows the issue. ↩