skip to content

What is the type of a 'throw' expression in Kotlin, and how does the Nothing type make throw usable in places that expect a value?

level: seniorimportance: should knowfreq 52%

answer

  1. throw has type Nothing
  2. Nothing = bottom type, subtype of all, no instances
  3. Enables ?: throw and Nothing-returning fail()
  4. Marks following code unreachable
  5. Nothing vs Nothing? vs Unit

basics

~20 s

A throw expression has type Nothing, the type with no values that is a subtype of every type. Because it fits anywhere, you can use throw on the right side of ?: (Elvis), as a when branch, or as a single-expression function body.

solid answer

~40 s

`throw` is an **expression** of type `Nothing`. `Nothing` is the bottom type: it has no instances and is a subtype of every other type. Since it's assignable to anything, `throw` can appear where a value is expected — most commonly as the right operand of the Elvis operator: `val name = user.name ?: throw IllegalArgumentException("missing")`. The compiler also uses `Nothing` for control-flow analysis: a function returning `Nothing` (like `kotlin.error(...)` or `TODO()`) tells the compiler that code after the call is unreachable, so smart casts and definite-assignment analysis carry past it. `Nothing?` is the type of `null` alone. A `when` branch or `try` block whose last action is `throw` has type `Nothing`, which is why such branches don't widen the overall expression type. This is what makes exhaustive `when` and expression-style try compose cleanly.

code

kotlin · 6 lines
kotlin
fun fail(msg: String): Nothing = throw IllegalStateException(msg)

fun firstWord(s: String?): String {
    val text = s ?: fail("input was null") // fail() is Nothing, so text is String
    return text.substringBefore(' ')       // reachable only when s != null
}

go deeper

for a junior

Knows you can write '?: throw' for a missing value.

for a middle

States that throw has type Nothing and that it fits where a value is expected.

for a senior

Explains Nothing as the bottom type and how it drives smart casts and unreachable-code analysis.

for a principal

Designs APIs around Nothing-returning helpers and reasons about subtyping/variance implications of the bottom type.

## throw is an expression, not a statement In Kotlin `throw` evaluates to a value of type **`Nothing`**. ## What is Nothing? `Nothing` is the **bottom type**: - It has **no instances** — you can never hold a `Nothing` value. - It is a **subtype of every type** (`Int`, `String`, `User`, ...). Because it's a subtype of everything, an expression of type `Nothing` can be used wherever **any** type is expected. A `throw` never actually produces a value (it unwinds the stack), so giving it the type that fits everywhere is sound. ## Idiomatic uses ### Elvis with throw ```kotlin val id = request.id ?: throw IllegalArgumentException("id required") // id is smart-cast to non-null here ``` `?:` requires both sides to share a type. The left is `Int?`; the right (`throw ...`) is `Nothing`. The common type becomes `Int`, and after the line `id` is non-null. ### Single-expression function ```kotlin fun fail(msg: String): Nothing = throw IllegalStateException(msg) ``` Declaring the return type `Nothing` lets callers use it like a value-producing expression. ### when branch ```kotlin val label = when (status) { Status.OK -> "ok" Status.FAIL -> throw IllegalStateException("failed") // type Nothing } ``` The throwing branch has type `Nothing`, so it doesn't force `label` to widen beyond `String`. ## Compiler control-flow benefits A call to a `Nothing`-returning function marks subsequent code **unreachable**: ```kotlin fun pick(x: Int?): Int { if (x == null) error("null") // kotlin.error returns Nothing return x // x smart-cast to Int; reachable only if non-null } ``` Stdlib helpers `kotlin.error(message): Nothing`, `TODO(): Nothing`, and `kotlin.require`/`check` (which throw on failure) all leverage this. ## Nothing vs Nothing? vs Unit - **`Nothing`**: no values; means "never returns normally." - **`Nothing?`**: the type whose only value is `null`. - **`Unit`**: exactly one value (`Unit`); means "returns, but no meaningful value" — the opposite end from `Nothing`. ## Key terms - **Bottom type**: subtype of all types, with no instances. - **Smart cast**: compiler narrowing a nullable to non-null after a check. - **Definite-assignment/reachability analysis**: how the compiler proves code after a `Nothing` call can't run.

  • Why can 'val x: Int = y ?: throw ...' compile when throw doesn't produce an Int?
    throw has type Nothing, a subtype of Int, so the Elvis result type is Int; the throw branch never returns a value anyway.
  • What return type would you give a function that always throws?
    Nothing — it tells the compiler the function never returns normally and that code after the call is unreachable.

Nothing is a universal adapter plug: it fits every socket precisely because it never actually delivers power.

saying these in an interview costs you the question

  • Saying throw is a statement with no type
  • Confusing Nothing with Unit
  • Thinking Nothing has instances
  • Not knowing Nothing is a subtype of every type
  • Unaware that Nothing enables unreachable-code analysis

context