---
title: "A typealias can take a type parameter"
description: "Naming a completion handler once and writing Handler<Post> at each call site. It gives you readability and a single place to change the signature. It does not give you type safety."
author: "Omar Albeik"
date: 2019-12-05
type: note
topics: [swift, api-design, software, engineering]
language: en
reading_time_minutes: 2
canonical_url: https://omaralbeik.com/en/blog/generics-in-typealias
translation_url: https://omaralbeik.com/ar/blog/generics-in-typealias
source_url: https://omaralbeik.com/en/blog/generics-in-typealias.md
---

# A typealias can take a type parameter

A `typealias` does one thing: it gives an existing type a second name. Apple's
own `TimeInterval` is one, aliasing `Double`. It says what the number means,
and it leaves room for the underlying type to change without every mention of
it changing too.

The version I use most often takes a type parameter:

```swift
struct Service {
  typealias Handler<Response> = (Result<Response, APIError>) -> Void

  func fetchPost(id: Int, _ completion: @escaping Handler<Post>) { ... }
  func fetchPosts(_ completion: @escaping Handler<[Post]>) { ... }
  func fetchBooks(_ completion: @escaping Handler<[Book]>) { ... }
}
```

Without it, each of those signatures carries
`(Result<Post, APIError>) -> Void` in full, and the shape of the API — every
call returns a `Result` with the same error type — is something the reader has
to assemble from three lines that all look slightly different. With it, the
shape is stated once and only the response type changes.

It also gives you somewhere to make a change. When the error type moves from
`APIError` to something else, it moves in one line rather than in every
signature that mentions it.

The other use is shortening a name you did not choose:

```swift
final class Service {
  typealias Book = SLBSomeLibraryServiceBookModel

  func loadBooks() -> [Book] { ... }
}
```

That is safe inside a type, where the alias is scoped and a reader can find the
declaration. At file scope it needs more care: `Book` from three different
modules means three different things.

What none of this gives you is type safety. `Handler<Post>` and
`(Result<Post, APIError>) -> Void` are the same type, not two types that happen
to be spelled differently — there is no distinction the compiler will enforce
and no overload it will resolve differently. If you want the compiler to know
that a service's completion is not just any closure, the alias is the wrong
tool and a wrapper type is the right one.

It is documentation that the compiler checks for spelling. It is not a type.

Antoine van der Lee has
[a longer piece on typealias](https://www.avanderlee.com/swift/typealias-usage-swift/)
that is worth the ten minutes.
