Contents

Typealias vs. inline value class

Normally, Typealias and inline value class (which I’ll refer to as value class throughout this text) are utilized for different purposes. However, developers might occasionally use one for the other. Let’s explore some examples and clarify the differences.

Typealias

kotlinlang.org does a pretty good job explaining Typealias:

Type aliases provide alternative names for existing types. If the type name is too long you can introduce a different shorter name and use the new one instead.

For instance, it’s often tempting to shrink collection types:

1
2
3
typealias Node2DArray = List<List<Node>>

typealias FileTable<K> = MutableMap<K, MutableList<File>>

You can have new names for inner and nested classes:

1
2
3
4
class A {
    inner class Inner
}
typealias AInner = A.Inner

Inline value class

Let’s see how kotlinlang.org defines a value class:

Sometimes it is useful to wrap a value in a class to create a more domain-specific type. Kotlin introduces a special kind of class called an inline class. Inline classes are a subset of value-based classes. They don’t have an identity and can only hold values.

To declare a value class, use the value modifier before the name of the class:

1
2
3
// For JVM backends
@JvmInline
value class Password(private val s: String)

A value class must have a single property initialized in the primary constructor. At runtime, instances of the value class will be represented using this single property:

1
2
3
// No actual instantiation of class 'Password' happens
// At runtime 'securePassword' contains just 'String'
val securePassword = Password("Don't try this in production")

Use cases

Let’s consider the following simple data model Person:

1
2
3
4
5
6
data class Person(
    val name: String,
    val family: String,
    val age: Int,
    val height: Int,
)

If you’re wondering how to ensure that the correct arguments are passed for similarly typed parameters like name and family, or age and height, Kotlin’s answer is the value class:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
@JvmInline
value class Name(val value: String)

@JvmInline
value class Family(val value: String)

@JvmInline
value class Age(val value: Int)

@JvmInline
value class Height(val value: Int)

data class Person(
    val name: Name,
    val family: Family,
    val age: Age,
    val height: Height,
)

Therefore, the caller needs to use the correct argument type for each corresponding parameter, as follows:

1
Person(Name("John"), Family("Doe"), Age(27), Height(180))

Using typealias in this scenario is not a solution to the aforementioned problem:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
typealias Name = String
typealias Family = String
typealias Age = Int
typealias Height = Int

data class Person(
    val name: Name,
    val family: Family,
    val age: Age,
    val height: Height,
)

Because no rule is enforced at the call site:

1
Person("Doe", "John", 27, 180)
Tip 1
Type aliases do not introduce new types. They are equivalent to the corresponding underlying types. When you define typealias Name = String and use Name in your code, the Kotlin compiler always expands it to String.
Tip 2
Value classes introduce a truly new type, contrary to type aliases which only introduce an alternative name (alias) for an existing type.
Tip 3
Value classes are compiled to their underlying type.

If you’d like to learn more about value class, you can check here.