11

So far I understand that the typealias is a named alias of an existing type. By using typealias, I could do something like:

typealias MyString = String
var str: MyString?

typealias Strings = [String]
var strs: Strings?

which leads to declare str variable as String and strs as an Array of strings.

Even for a custom type:

class MyClass {}
typealias MyClsType = MyClass
var myClass: MyClsType

However, it seems a little unuseful; Logically, what is the purpose of declaring -for example- var str: MyString? to be a String instead of var str: String?? even more, var str: String is more expressive.

Ahmad F
  • 30,560
  • 17
  • 97
  • 143

2 Answers2

29

Actually, there is no doubt that creating a typealias for -let's say- String: typealias MyString = String wouldn't be that useful, (I would also assume that declaring a typealias for Dictionary with specific key/value type: typealias CustomDict = Dictionary<String, Int> might not be that useful to you.

However, when it comes to work with compound types you would definitely notice the benefits of type aliasing.

Example:

Consider that you are implementing manager which repeatedly work with closures with many parameters in its functions:

class MyManager {
    //...

    func foo(success: (_ data: Data, _ message: String, _ status: Int, _ isEnabled: Bool) -> (), failure: (_ error: Error, _ message: String, _ workaround: AnyObject) -> ()) {
        if isSuccess {
            success(..., ..., ..., ...)
        } else {
            failure(..., ..., ...)
        }
    }

    func bar(success: (_ data: Data, _ message: String, _ status: Int, _ isEnabled: Bool) -> (), failure: (_ error: Error, _ message: String, _ workaround: AnyObject) -> ()) {
        if isSuccess {
            success(..., ..., ..., ...)
        } else {
            failure(..., ..., ...)
        }
    }

    // ...
}

As you can see, the methods signatures looks really tedious! both of the methods take success and failure parameters, each one of them are closures with arguments; Also, for implementing similar functions, it is not that logical to keep copy-paste the parameters.

Implementing typealias for such a case would be so appropriate:

class MyManager {
    //...

    typealias Success = (_ data: Data, _ message: String, _ status: Int, _ isEnabled: Bool) -> ()
    typealias Failure = (_ error: Error, _ message: String, _ workaround: AnyObject) -> ()

    func foo(success: Success, failure: Failure) {
        if isSuccess {
            success(..., ..., ..., ...)
        } else {
            failure(..., ..., ...)
        }
    }

    func bar(success: Success, failure: Failure) {
        if isSuccess {
            success(..., ..., ..., ...)
        } else {
            failure(..., ..., ...)
        }
    }

    // ...
}

Thus it would be more expressive and readable.


Furthermore, you might want to check a medium story I posted about it.

Ahmad F
  • 30,560
  • 17
  • 97
  • 143
  • 3
    `typealias` for a `String` can be useful: - provides semantic meaning to the reader: `let result: Token` rather than `let result: String` would be a little more meaningful. - if you every decide to migrate from a primitive value to a custom type, the type alias guides you. E.g. if `Token` becomes a `struct`, then the compiler will tell you the places of use. The first compile after changing the `typealias` to a `struct` will compile as is! – raheel Nov 07 '18 at 20:33
  • I'm on the same dilemma right now. Got a bunch of long generic types like `Results` through `Results` (using `ObjcX` as an example) and some dictionaries with similar forms: `[ObjA:[ObjB]]` where using names such as ObjAQueryResult or ObjAObjBMapping makes way more sense as is just less code to type. BUT, I feel that when another dev takes over, there will be a extra cognitive load, however small, in looking up what each of this typealiases is, at least until they are used to this specific part of the code, which is already complex anyway. – cumanzor Jun 04 '19 at 06:47
1

The common way to use typealias for me is working with closures:

typealias VoidClosure = () -> Void

func updateFrom(completion: @escaping VoidClosure) { }

  • Not only for closures, mentioning "compound types" would be more accurate. You could check link of compound types in my answer to review what does it mean (Types). – Ahmad F Nov 22 '17 at 10:06
  • @AhmadF yeah. I totally agree with you. It' makes code easier to read when some complex arguments of types appeared – Serg Tsarikovskiy Nov 22 '17 at 11:00