Swift has five key path types, but we can categorize them into two groups based on their functions.
- Read-only key paths.
- Writable key paths (Can read and write).
We have three read-only key paths.
And two writable key paths.
I will only focus on three basic types of key paths in this article.
1 KeyPath: A read-only access to a property. Root type can be both value/reference semantics.
2 WritableKeyPath: Provides read-write access to a mutable property with value semantics (such as struct and enum).
3 ReferenceWritableKeyPath: Provides reading and writing to a mutable property with reference semantics (such as class).
How can key path type inferred
In the last section, when we construct key paths, you can see that we only get KeyPath and WritableKeyPath.
let firstIndexInteger = \[Int][0]
// WritableKeyPath<[Int], Int>
let firstInteger = \Array<Int>.first
// KeyPath<[Int], Int?>
Key path infers from the properties/subscripts and a root type.
If properties or subscripts are read-only (such as
letorsubscriptwith onlyget),KeyPathis inferred.If it is mutable (such as
varorsubscriptwithget/set).
-- With a root of value types (such asstructandenum),WritableKeyPathis inferred.
-- With a root of reference types (such asclass),ReferenceWritableKeyPathis inferred.
We declare every property with let, so we get KeyPath as a result.
let userRole = \User.role
// KeyPath<User, Role>
let streetAddress = \User.address?.street
// KeyPath<User, String?>
first and debugDescription are read-only computed properties, so we also get KeyPath as a result.
let stringDebugDescription = \String.debugDescription
// KeyPath<String, String>
let firstInteger = \Array<Int>.first
// KeyPath<[Int], Int?>
We get WritableKeyPath when reference array subscript because it is a read-write subscript (get/set).
subscript(index: Int) -> Element { get set }
let firstIndexInteger = \[Int][0]
// WritableKeyPath<[Int], Int>
If we change the name property to var, we will get WritableKeyPath when reference \User.name.
struct User {
var name: String
}
\User.name
// WritableKeyPath<User, String>
If we change User to class, key path to var and let will be ReferenceWritableKeyPath and KeyPath, respectively.
class User {
var name: String
let email: String
init(name: String, email: String) {
self.name = name
self.email = email
}
}
\User.name
// ReferenceWritableKeyPath<User5, String>
\User.email
// KeyPath<User, String>
Next Article: KeyPath Usage in Swift
Previous Article: KeyPath in Swift
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
Top comments (0)