skip to content

In a Kotlin Multiplatform project, what does `actual typealias UUID = java.util.UUID` do, and why would you use it instead of writing an `actual class`?

level: juniorimportance: must knowfreq 55%

answer

  1. typealias = new name, not new type
  2. actual satisfies expect by pointing at JDK type
  3. no wrapper, no delegation, members free
  4. java.util.UUID is the class itself
  5. structural match required

basics

~10 s

It says: on this platform, the shared expect class UUID is exactly the platform's own UUID type. You reuse an existing native type directly instead of writing a wrapper class around it.

solid answer

~40 s

In common code you declare `expect class UUID`. Each platform must supply a matching `actual`. With `actual typealias UUID = java.util.UUID`, the JVM target satisfies the `expect` by pointing the name `UUID` at the already-existing `java.util.UUID`. No new class is generated and no wrapper/delegation is written — at compile time `UUID` simply *is* `java.util.UUID`, so all its constructors, methods (`randomUUID()`, `toString()`), and equality come for free. You use this when a perfectly good platform type already exists and writing an `actual class` would just mean re-declaring or delegating every member by hand. It is the idiomatic way to bridge shared API to JDK/native types like `UUID`, `BigDecimal`, or `AtomicInteger`.

code

kotlin · 11 lines
kotlin
// commonMain
expect class UUID {
    override fun toString(): String
    companion object { fun randomUUID(): UUID }
}

// jvmMain — satisfied with zero wrapper code
actual typealias UUID = java.util.UUID

// commonMain usage works on JVM thanks to the alias
fun newId(): UUID = UUID.randomUUID()

go deeper

for a junior

Knows expect/actual pair the contract with a per-platform implementation and that the alias reuses an existing type.

for a middle

Explains typealias creates no new type and members come for free, and contrasts with actual class.

for a senior

Discusses structural-match requirement, interop benefits, and when an alias is impossible (must wrap).

for a principal

Frames it as an API-design lever for binary/source compatibility and library boundary shaping across targets.

## The problem `expect`/`actual` solves Kotlin Multiplatform (KMP) lets you write **common** code shared across targets (JVM, Native, JS, Wasm). When common code needs something that only exists per-platform, you declare an **`expect`** declaration — a contract with no body — and each target provides a matching **`actual`** implementation. ```kotlin // commonMain expect class UUID { override fun toString(): String companion object { fun randomUUID(): UUID } } ``` ## Two ways to provide the `actual` 1. **`actual class`** — you write a real class (often wrapping/delegating to a platform type). 2. **`actual typealias`** — you alias the `expect` name to an **existing** platform type. ```kotlin // jvmMain actual typealias UUID = java.util.UUID ``` A **typealias** introduces an alternative *name* for an existing type; it creates **no new type**. So after this alias, in JVM code the name `UUID` and `java.util.UUID` are literally interchangeable — same class, same bytecode, same methods, same `equals`/`hashCode`. ## Why prefer the typealias - **Zero wrapper cost.** No boxing, no delegation, no re-implementing members. `java.util.UUID.randomUUID()` already exists, so the companion/members are satisfied automatically. - **Seamless interop.** Java libraries returning `java.util.UUID` plug straight into your common `UUID` API with no conversion. - **Less code to maintain.** An `actual class` forces you to redeclare every member; the alias inherits them. ## What the compiler checks The aliased type must structurally match the `expect`: every member the `expect` declares (methods, properties, constructors, companion members) must already exist on `java.util.UUID` with compatible signatures, else you get an *actualization* error. ## When you can't use it If no single platform type matches the `expect` surface, or you need extra behavior the platform type lacks, fall back to `actual class` (possibly wrapping the platform type).

  • Does `actual typealias` create a new class at runtime?
    No. A typealias is purely a compile-time name; at runtime there is only `java.util.UUID`. No extra class or object is generated.
  • What happens if `java.util.UUID` is missing a method the `expect` declares?
    Compilation fails with an actualization error: the aliased type must provide every member the `expect` declares with a compatible signature.

It's like a nickname: 'UUID' is just another name for the same person java.util.UUID — not a new person who imitates them.

saying these in an interview costs you the question

  • Saying the typealias generates a wrapper class
  • Claiming it copies methods into a new type
  • Thinking it converts/boxes values at runtime
  • Believing typealias creates a distinct, non-interchangeable type

context