Skip to main content

Type checks and smart casts

is tests a type. When control flow proves the test, Kotlin often exposes the narrower type without an explicit cast.

fun render(value: Any): String = when (value) {
is String -> "Text length: ${value.length}"
is Int -> "Number doubled: ${value * 2}"
else -> "Unsupported"
}

Inside the first branch, value is known to be String; inside the second, it is Int.

Guard clauses​

fun normalizedName(value: Any?): String {
if (value !is String) return "Unknown"
return value.trim()
}

After the early return, every remaining path proves that value is a String. Guard clauses also keep the happy path less indented.

Why a smart cast can fail​

Kotlin smart-casts only when it is sure the value cannot change after the check. A mutable property might have one value during the check and another during the next read, so the compiler may refuse the smart cast.

class Profile(var nickname: String?)

fun length(profile: Profile): Int {
val nickname = profile.nickname // stable snapshot
return if (nickname != null) nickname.length else 0
}

The local val reads nickname once. Kotlin knows this local value cannot be reassigned, so the null check remains valid when length is called.

Explicit and safe casts​

  • value as Type throws ClassCastException if wrong.
  • value as? Type returns null if wrong.
val routeId: String? = arguments["id"] as? String
Boundary rule

Values from a Bundle, Intent, network response, database, reflection, or Java may not have the expected type. Safely cast and validate them when they enter your code. Then pass a clear Kotlin type through the application instead of passing Any? everywhere.

Interview-ready answer

A smart cast is Kotlin automatically treating a value as a more specific type after a successful check. It works only when the compiler can prove the value will not change between the check and its use. For a mutable property, copy one read into a local val when that behavior is correct.

Open in Kotlin Playground

Interview check​

Why does checking a mutable property not always smart-cast it?

Because reading the property again may return a different value. Copy it to a local val when you want to check and use the same captured value.