What is a function-type typealias in Kotlin, and why would you declare something like `typealias Handler = (Event) -> Unit`?
answer
- typealias = nickname for a type
- Same type, fully interchangeable
- Zero runtime cost, no wrapper class
- Top-level only
- Readability, not type safety
basics
~10 sIt gives a short, meaningful name to a function type. Instead of writing (Event) -> Unit everywhere, you write Handler. It is just an alias, so the two names mean exactly the same type.
solid answer
~40 sA `typealias` introduces an alternative name for an existing type; for function types it makes higher-order signatures readable. `typealias Handler = (Event) -> Unit` lets you write `fun on(h: Handler)` instead of repeating `(Event) -> Unit`. It is purely a compile-time alias: `Handler` and `(Event) -> Unit` are the *same* type, fully assignment-compatible in both directions, with no wrapper, runtime cost, or new class. It does not create encapsulation or type-safety: any `(Event) -> Unit` lambda is a valid `Handler`. Typealiases must be declared at the top level (file scope), not inside a class or function. They are mainly a documentation/readability tool for parameters, return types, and complex generic function signatures.
code
kotlin · 11 linestypealias Handler = (Event) -> Unit
class Bus {
private val handlers = mutableListOf<Handler>()
fun on(h: Handler) { handlers += h } // reads cleanly
fun emit(e: Event) = handlers.forEach { it(e) }
}
// A plain lambda is a valid Handler — they are the same type:
val bus = Bus()
bus.on { event -> println("got $event") }go deeper
Knows typealias names a type and improves readability of callback parameters.
Explains it is purely an alias — same type, interchangeable, no runtime cost, top-level only.
Contrasts with fun interface / value class and articulates the no-type-safety tradeoff and when each is appropriate.
Frames typealias as a documentation tool within an API design strategy, weighing readability vs. nominal typing across a module's public surface.
## What `typealias` does A **typealias** declares an alternative *name* for a type that already exists. The keyword is `typealias`. For a **function type** (a type describing a function value, written `(Params) -> ReturnType`), it lets you replace a hard-to-read inline type with a domain word. ```kotlin typealias Handler = (Event) -> Unit fun register(name: String, handler: Handler) { /* ... */ } // identical to: fun register(name: String, handler: (Event) -> Unit) { /* ... */ } ``` ## Key property: it is an *alias*, not a new type After `typealias Handler = (Event) -> Unit`, the names `Handler` and `(Event) -> Unit` are **fully interchangeable**. The compiler erases the alias before type checking, so: - A plain lambda `{ e: Event -> ... }` is a valid `Handler`. - A `Handler` value can be passed anywhere `(Event) -> Unit` is expected, and vice-versa. - There is **no wrapper class, no boxing, no runtime overhead** — `::class` / reflection see the underlying function type. This is the big difference from wrapping a function in a `class` or `value class`: an alias gives you readability but **zero** extra type safety. If you want a distinct, non-interchangeable type, you need a real class, not a typealias. ## Where you can declare it Typealiases must be **top-level** declarations (directly in a file). You cannot put one inside a class body or a function. They can be `private`/`internal` to limit visibility to a file/module. ## Why use it - **Readability** of higher-order signatures — `Validator<T>` reads better than `(T) -> Boolean`. - **Single point of change** — if the callback shape evolves, you update the alias once (callers using the alias still need to match the new shape, but the intent stays centralized). - **Self-documenting APIs** — names like `Reducer`, `Middleware`, `Comparator`-style aliases convey intent. ```kotlin typealias Validator<T> = (T) -> Boolean val notBlank: Validator<String> = { it.isNotBlank() } ``` ## What it is NOT - Not a new class or `interface` — use a `fun interface` if you need a named SAM type with its own identity. - Not encapsulation — it does not hide or restrict the underlying type.
- Can you declare a typealias inside a class?No. Typealiases must be top-level declarations in a file; they cannot be nested in a class or function.
- Does a typealias give you any extra type safety?No. It is just another name for the same type — any value of the underlying function type is accepted. For a distinct type use a class, value class, or fun interface.
Like a contact name in your phone: 'Mom' and the actual phone number are the same number, just one is easier to read.
saying these in an interview costs you the question
- Claiming a typealias creates a new type or class
- Thinking it adds type safety or prevents passing a raw lambda
- Saying it has runtime overhead or boxes the function
- Believing it can be declared inside a class or function body
- Confusing it with a fun interface (SAM type)