KeyPath in Swift: Syntax.
Sergey Leschev
Posted on January 29, 2023
KeyPath is a type that represent a references to properties and subscripts. Since it is a type, you can store it in a variable, pass it around, or even perform an operation on a key path. We can use a key path to get/set their underlying values at a later time.
Let's create a few structs, which we will use as an example.
// 1
struct User {
let name: String
let email: String
let address: Address?
let role: Role
}
// 2
struct Address {
let street: String
}
// 3
enum Role {
case admin
case member
case guest
var permissions: [Permission] {
switch self {
case .admin:
return [.create, .read, .update, .delete]
case .member:
return [.create, .read]
case .guest:
return [.read]
}
}
}
// 4
enum Permission {
case create
case read
case update
case delete
}
1 We declare a User
struct which stores name
, email
, address
, and role
.
2 Address
is a struct that keeps the information about the address. For brevity, we only have a street
name.
3 We have all possible roles as an enum, Role
. It also holds a computed property that returns an array of Permission
that particular have.
4 Permission
is an enum of all possible actions a user can make.
Key Path Expression
Key Path expressions have the following form:
\type name.path
Type Name
The type name is the name of a concrete type, including any generic parameters if the types have one.
// 1
let stringDebugDescription = \String.debugDescription
// KeyPath
// 2
let userRole = \User.role
// KeyPath
// 3
let firstIndexInteger = \[Int][0]
// WritableKeyPath<[Int], Int>
// 4
let firstInteger = \Array.first
// KeyPath<[Int], Int?>
1 Key path which type is a String
.
2 Key path which type is our custom struct, User
.
3, 4 We can reference array by the full type name (Array
) or shortened form ([]
), but you have to also specify its generic type, [Int] and Array<Int>
.
Like most things in Swift, type names can be omitted in contexts where type can be inferred.
In the following example, type name can be inferred from the explicit variable type, so we can leave the type name blank. Notice that we still need \ and .
// \String.debugDescription => \.debugDescription
let stringDebugDescription: KeyPath<String, String> = \.debugDescription
Path
The path
can be property names, subscripts, optional-chaining expressions, and forced unwrapping expressions. Basically, everything that we usually use when reference value on an instance object/struct.
// 1
let userName = \User.name
// KeyPath
// 2
let firstIndexInteger = \[Int][0]
// WritableKeyPath<[Int], Int>
// 3
let streetAddress = \User.address?.street
// KeyPath
// 4
let forceStreetAddress = \User.address!.street
// KeyPath
1 Key path which path is a property name.
2 Key path which path is a subscript.
3 Key path which path is an optional-chaining to a property.
4 Key path which path is forced unwrapping to a property name.
Path can be repeated as many times as needed, and it can also refer to a computed property name.
let userRolePermissions = \User.role.permissions
// KeyPath<User, [Permission]>
let firstUserRolePermissions = \User.role.permissions[0]
// KeyPath<User, Permission>
Syntax
I think the syntax of a key path should become clearer to you at this point. Since KeyPath
is a way to define a reference to properties and subscripts, that means it can use any expression we use to reference properties and subscripts from an instance.
To convert a normal reference to a key path, we replace any class/struct instance with a backslash ( \
) followed by that instance type.
let streetValue = user.address?.street
// KeyPath version referencing the same value.
let streetKeyPath = \User.address?.street
Next Articles:
Contacts
I have a clear focus on time-to-market and don't prioritize technical debt. And I took part in the Pre-Sale/RFX activity as a System Architect, assessment efforts for Mobile (iOS-Swift, Android-Kotlin), Frontend (React-TypeScript) and Backend (NodeJS-.NET-PHP-Kafka-SQL-NoSQL). And I also formed the work of Pre-Sale as a CTO from Opportunity to Proposal via knowledge transfer to Successful Delivery.
๐ฉ๏ธ #startups #management #cto #swift #typescript #database
๐ง Email: sergey.leschev@gmail.com
๐ LinkedIn: https://linkedin.com/in/sergeyleschev/
๐ LeetCode: https://leetcode.com/sergeyleschev/
๐ Twitter: https://twitter.com/sergeyleschev
๐ Github: https://github.com/sergeyleschev
๐ Website: https://sergeyleschev.github.io
๐ Reddit: https://reddit.com/user/sergeyleschev
๐ Quora: https://quora.com/sergey-leschev
๐ Medium: https://medium.com/@sergeyleschev
๐จ๏ธ PDF Design Patterns: Download
Posted on January 29, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.