It's been so fun to watch the Swift developer community experiment with Swift and to experiment with what idiomatic Swift will look like. No one really knows the answer yet, but we're starting to see some design patterns used more than others. We're seeing some language features used in key ways that define idiomatic Swift, and other language features that are being mostly ignored.
Regrettably, one of my favourite features of Swift has not enjoyed the meteoric rise in popularity I believe it deserves:
Type aliases allow developers to define synonyms for pre-existing types. It might sound dull because it is dull. In fact, its usefulness isn't even apparent when writing code, mostly when maintaining it.
But before I dig into how
typealias is useful, let's review what it is to make sure we're all on the same page. Developers use
typealias to create a new type identifier that's a synonym for another type. For example, we can declare
typealias BigNumber = Int64 and use "BigNumber" any place we could have used "Int64".
1 2 3 4 5 6 7 8 9
You can use
typealias for most any type: classes, enums, structs, tuples, closures, etc. Here are a few examples.
1 2 3 4
Now that we're familiar with
typealias, I want to discuss four examples that show how
typealias has helped us maintain code.
Promoting Existing Types Semantics
When writing web socket communication for eigen, Orta and I were using JSON Web Tokens to authenticate the user. If you've never used JWTs before, don't worry, here's the tl;dr JWTs are a way to authenticate users in a way that clients can cryptographically verify. It's basically a base64 encoded string of JSON.
Clients don't need to verify the JWT in order to use them, and in fact when Orta and I began using them, we treated them only as strings retrieved from one API and sent to another (like an access token). However, instead of using the
String type, I decided to define a
JWT type alias.
I used the new
JWT type throughout the code as a hint to other developers about what kind of string it is. This gave it some semantic meaning on top of being a string. Neat. Only later, when we needed to start decoding the JWT itself did this really come in handy.
After deleting the
typealias and replacing it with a class of the same name, we didn't have to worry about changing function definitions and property types all throughout our codebase. We made the changes locally, in one file, and most all the rest of our code still compiled. Pretty cool! Here's the relevant portion of the pull request that made that change.
Consolidating Tuple Types
I recently wrote about UICollectionView and how I used them to solve a difficult layout problem. I detailed how I created a pipeline of simple math functions that used previous results to calculate the next step of the layout. What I didn't mention was that I used tuples to help, specifically tuples with
Tuples are useful for composing several different values into a lightweight type. Think of tuples as junior structs. I was writing functions to do some calculations and return their result as a tuple. Something like this:
And because of how the layout pipeline worked, I then needed to use the same tuple as a parameter for the next function.
Any time you use the same tuple type more than once, consider making a
typealias. In this case, the code became a lot shorter and easier to skim and understand.
1 2 3 4 5 6
If we need to change something about the tuple later on, we only need to change it in one place. We've also made it easier to promote this tuple to a struct or class later on, just like in the JWT example, because all the functions are already referring to it as its own type. You can check out how we used type alias'd tuples in the code.
Defining Closures Signatures
Objective-C developers, burdened with arcane syntax for blocks, use C's
typedef to isolate that syntax strangeness in one place. And even though Swift's closure syntax is awesome, we can still benefit from Objective-C's example – we can use type aliases for closure signatures.
Moya uses this technique quite a bit, because it has so many closures. Let's take a look at the
StubClosure, which defines if (and how) a network request should be stubbed.
We use this type as an initializer parameter instead of the full closure syntax, making our code a lot shorter and more legible. Nice! Since the user usually doesn't want to customize this parameter, so we've defined a default value.
1 2 3
MoyaProvider has a class function on it called
NeverStub whose type matches our closure.
1 2 3
This particular function doesn't use the
typealias, but another one does. We have a function named
DelayedStub that returns the
typealias instead of the raw closure. Take a look!
1 2 3
Super cool! Closures are a powerful tool in Swift already, but by using a
typealias, we refer to it as
StubClosure throughout our code.
In isolation, this gain may not seem significant, but the dividends have accrued dramatically for the project.
typealias has made it easy to maintain Moya as it has evolved alongside Swift. Check out more examples of type aliasing closures in this eigen class, which uses them for dependency injection.
The last example I want to discuss is extensions, specifically extensions to your own types.
When writing classes, especially view controllers, developers have a habit of writing long, unwieldy files that are difficult to navigate and maintain. Preventing such files is far easier than fixing them, which is why I use
typealias early, and I use it often.
I recommend using a descriptive
typealias that is private to your file, and then extending that
typealias so you can keep things neat and tidy. It's a bit confusing, so let's take a look at an example.
1 2 3 4 5 6 7 8 9
We're still extending the view controller, but specifically we're extending the
typealias so that the extension has a helpful name. This is another way that
typealias can help add semantic meaning to your code.
Beyond helping you find code quickly, having code in extensions also makes it way easier to move that extension to another file or create a new helper class altogether. So not only does it keep classes tidy, but it also helps you keep classes small.
This technique can also serve as a workaround for Swift's awful Xcode sectioning syntax.
You can search through eigen for more examples of using a private
typealias to divide your code into manageable pieces.
Look, I'm not saying that using
typealias more is universally a good idea. You might disagree with some of the use cases in this post, which is fine! And this isn't meant to be an exhaustive list of examples, either.
My point is, used in a few key ways,
typealias has helped me maintain my code more easily. It's a good tool to be familiar with. Even if it won't revolutionize the way you write software,
typealias can help make your job a smidgen easier, and who could argue with that?