Alter type with typealias

Kotlin Vocabulary: typealias

Florina Muntenescu
Android Developers
Published in
3 min readJan 16, 2020

--

When type definitions distract from what your code means because they’re not readable, expressive or just too long, Kotlin has just the right feature for you: typealias! Typealias allows you to provide alternate names for class or functions types without introducing a new type.

Typealias usage

You can use type aliases to name a function type:

typealias TeardownLogic = () -> Unit
fun onCancel(teardown : TeardownLogic){ }
private typealias OnDoggoClick = (dog: Pet.GoodDoggo) -> Unit
val onClick: OnDoggoClick

The disadvantage of this is that the name hides the parameters passed to the function, decreasing the readability:

typealias TeardownLogic = () -> Unit //or
typealias TeardownLogic = (exception: Exception) -> Unit
fun onCancel(teardown : TeardownLogic){
// can’t easily see what information we have
// available in TeardownLogic
}

Typealias allows you to shorten long generic names:

typealias Doggos = List<Pet.GoodDoggo>fun train(dogs: Doggos){ … }

While this is possible ask yourself whether indeed you should do it. Does using a type alias indeed make your code more meaningful and readable?

Ask yourself whether using a type alias makes your code more understandable.

If you’re working with a long class name, you could use typealias to shorten it:

typealias AVD = AnimatedVectorDrawable

But for this use case, a better fit would be using an import alias:

import android.graphics.drawable.AnimatedVectorDrawable as AVD

In this case using a shortcut doesn’t really help with increasing the readability and the IDE would help with auto-completing the name of the class.

But, import aliases become especially useful when you need to disambiguate between classes with the same name, coming from different packages:

import io.plaidapp.R as appRimport io.plaidapp.about.R

Type aliases are defined outside classes so make sure you consider their visibility when using them.

Typealias usage in multi-platform projects

When working with multi-platform projects you can specify interfaces in the common code that are then implemented in the platform code. To make this easier, Kotlin provides a mechanism of expected and actual declarations.

The interfaces in the common code are the expected declarations, defined using the expect keyword. The implementation in the platform code is defined using the actual keyword. If the implementation already exists in one of the platforms and has all the expected methods with the exact same signatures, then you can use typealias to map the name of the class to the expected name.

expect annotation class Testactual typealias Test = org.junit.Test

Under the hood

Type aliases don’t introduce new types. For example, the decompiled code for train function will just use a List:

// Kotlin
typealias Doggos = List<Pet.GoodDoggo>
fun train(dogs: Doggos) { … }
// Decompiled Java code
public static final void train(@NotNull List dogs) { … }

Type aliases don’t introduce new types.

You shouldn’t rely on type aliases for compile time type checks. Instead, you should consider using a different type or an inline class. For example, let’s say that we have the following function:

fun play(dogId: Long)

Creating a type alias to Long won’t help us prevent errors when we’re trying to pass the wrong id:

typealias DogId = Longfun pet(dogId: DogId) { … }fun usage() {
val cat = Cat(1L)
pet(cat.catId) // compiles
}

Type aliases are a way to provide a shorter or more meaningful name for an existing type. If what you are looking for is additional safety, you probably want to create a new type instead.

--

--