typealias
is used to rename an existing type. By doing this, we can change our code and make it more readable, and clearer in context. The using of typealias
is as simple as a normal assignment. A new name could be assigned to an old type with an equality sign. Take an example, when handling some concepts in a 2D plane, by default we may use Double
as the type of distance, and CGPoint
referring the position:
func distanceBetweenPoint(point: CGPoint, toPoint: CGPoint) -> Double {
let dx = Double(toPoint.x - point.x)
let dy = Double(toPoint.y - point.y)
return sqrt(dx * dx + dy * dy)
}
let origin: CGPoint = CGPoint(x: 0, y: 0)
let point: CGPoint = CGPoint(x: 1, y: 1)
let distance: Double = distanceBetweenPoint(origin, point)
It is fine in both mathematics and programming, but not so well in human understanding. The type of Double
or CGPoint
is only an abstract in mathematics. When reading this code, we have to convert them again in our brains: CGPoint
represents a point, and it is a position in the coordinate system we defined, while Double
is a number and means the distance between two positions.
So, why not use the words Position
and Distance
directly?
If we turn to use typealias
, we can write down these conversions in the code. So it becomes easier for us to read and maintain it:
typealias Location = CGPoint
typealias Distance = Double
func distanceBetweenPoint(location: Location,
toLocation: Location) -> Distance {
let dx = Distance(location.x - toLocation.x)
let dy = Distance(location.y - toLocation.y)
return sqrt(dx * dx + dy * dy)
}
let origin: Location = Location(x: 0, y: 0)
let point: Location = Location(x: 1, y: 1)
let distance: Distance = distanceBetweenPoint(origin, point)
The two versions do the same thing, but with the help of typealias
, we get some cleaner and more readable code.
There is nothing difficult for routine types. While it turns to generic, things get complicated soon. First of all, typealias
is unique. You can only set a specified type to a typealias
. Any attempt at setting a generic typealias will fail. For example, this code produces an error in compiling:
This is wrong code
class Person<T> {} typealias Worker = Person typealias Worker = Person<T> typealias Worker<T> = Person<T>
Once the generic type is determined, we can use typealias
to rename it:
class Person<T> {}
typealias WorkId = String
typealias Worker = Person<WorkId>
Conceptually, there are no generic protocols in Swift. But by using typealias we can declare a required alias for another type. A good example is GeneratorType
or SequenceType
in Swift. In these two protocols, Swift defines a typealias for the users of this protocol to implement:
protocol GeneratorType {
typealias Element
mutating func next() -> Self.Element?
}
protocol SequenceType {
typealias Generator : GeneratorType
func generate() -> Self.Generator
}
When we write a type conforming to this kind of protocol, except for implementing the methods, we have to specify a type for it. In fact, it is an abstract for a protocol.