skip to content

What is a top-level typealias in Kotlin, what can it and can't it do, and where must it be declared?

level: seniorimportance: should knowfreq 38%

answer

  1. Alias for an existing type, not a new type
  2. Compile-time substitution, zero runtime cost
  3. Top-level only - never inside class or function
  4. No extra type safety; use value class for that
  5. Can be generic: typealias Predicate<T>

basics

~20 s

A typealias gives an existing type a shorter or clearer name. It creates no new type - it is just an alias. In Kotlin it must be declared at the top level of a file, not inside a function or class body.

solid answer

~40 s

A typealias introduces an alternative name for an existing type: typealias Handler = (Event) -> Unit. It is a pure compile-time substitution - it does not create a new type, so Handler and (Event) -> Unit are fully interchangeable and assignment-compatible; no wrapping, no runtime cost, and is/as checks see through it. It can name function types, generic instantiations (typealias StringMap = Map<String, String>), and can itself be generic (typealias Predicate<T> = (T) -> Boolean). Crucially, type aliases may only be declared at the top level of a file - they cannot be nested in classes or functions. Because they erase to the underlying type, they provide no extra type safety; for distinct types use a value class (inline class) instead. Visibility modifiers (public/internal/private) apply.

code

kotlin · 7 lines
kotlin
typealias Callback<T> = (Result<T>) -> Unit

fun fetch(cb: Callback<String>) = cb(Result.success("ok"))

// Callback<String> IS (Result<String>) -> Unit - interchangeable
val c: (Result<String>) -> Unit = { }
fun use() = fetch(c)   // compiles: same type

go deeper

for a junior

Knows typealias is a shorter name for an existing type and lives at the top level.

for a middle

Explains it is compile-time substitution with no new type and can be generic over function/collection types.

for a senior

Contrasts typealias (no safety, zero cost) with value class (distinct type) and applies the top-level-only restriction correctly.

for a principal

Guides when aliases improve API readability vs. when domain types (value classes) are warranted, considering interop and refactor safety.

## What a typealias is `typealias` defines a second name for an existing type. Syntax: ```kotlin typealias Handler = (Event) -> Unit typealias StringMap = Map<String, String> typealias Predicate<T> = (T) -> Boolean // generic alias ``` It is resolved entirely at **compile time** by substitution. `Handler` and `(Event) -> Unit` are the *same* type to the compiler. ## What it does NOT do - It does **not** create a new, distinct type. There is **no** added type safety: a `typealias UserId = Int` is still just an `Int`, so you can pass any `Int` where a `UserId` is expected. - It adds **no runtime representation** - no wrapper object, no overhead. Reflection and `is`/`as` see the underlying type. ## Where it can be declared - top level only Type aliases must be **top-level** declarations in a file. You **cannot** declare a `typealias` inside a function body, and you cannot nest it as a member inside a class or interface. This is a deliberate language restriction. ```kotlin class Foo { // typealias Bar = Int // ERROR: nested type aliases are not allowed } fun work() { // typealias Local = Int // ERROR: not allowed inside a function } ``` ## Common uses - Shorten verbose generic/function types: `typealias ClickListener = (View, Int) -> Unit`. - Give domain meaning to a structure: `typealias Coordinates = Pair<Double, Double>`. ## typealias vs value class If you want a **distinct** type that prevents mixing `UserId` with a raw `Int`, use a `value class` (formerly inline class): ```kotlin @JvmInline value class UserId(val raw: Int) ``` Unlike a typealias, a `value class` is a real, type-safe type (with near-zero overhead via inlining where possible). ## Visibility A top-level `typealias` honors `public` (default), `internal`, and `private` (file-scoped) just like other top-level declarations.

  • Does typealias UserId = Int stop you passing a plain Int where a UserId is expected?
    No. It is the same type, so any Int is accepted. Use a value class for that safety.
  • Can you declare a typealias inside a class body?
    No. Type aliases are top-level only; nesting them in a class or function is a compile error.

A typealias is a nickname: calling Robert 'Bob' doesn't create a second person - both names point to exactly the same individual.

saying these in an interview costs you the question

  • Claiming typealias creates a new distinct type
  • Saying it adds type safety like a wrapper
  • Thinking it has runtime overhead or boxing
  • Believing you can declare it inside a function or class
  • Confusing typealias with import-as renaming semantics

context