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
let
orsubscript
with onlyget
),KeyPath
is inferred.If it is mutable (such as
var
orsubscript
withget/set
).
-- With a root of value types (such asstruct
andenum
),WritableKeyPath
is inferred.
-- With a root of reference types (such asclass
),ReferenceWritableKeyPath
is 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)