When to use typealias?

2020-06-16 09:02发布

问题:

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.

回答1:

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.



回答2:

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

typealias VoidClosure = () -> Void

func updateFrom(completion: @escaping VoidClosure) { }