> ## Documentation Index
> Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Kotlin When with Type Check

The Kotlin `when` construct facilitates type checking by evaluating a subject against specified types using the `is` and `!is` operators. It integrates directly with Kotlin's compiler-driven smart cast system, automatically casting the subject to the matched type within the lexical scope of the successful branch without requiring explicit cast operators (`as`).

## Syntax

```kotlin theme={"dark"}
when (subject) {
    is TypeA -> // subject is smart-cast to TypeA
    is TypeB -> // subject is smart-cast to TypeB
    !is TypeC -> // subject is guaranteed NOT to be TypeC
    else -> // Fallback branch
}
```

## Technical Mechanics

**1. Smart Casting and Scope**
When a branch condition like `is String` evaluates to `true`, the compiler tracks this type assertion. Within the right-hand side of that specific branch, the subject is treated as the asserted type. Properties and functions of that type can be invoked immediately.

```kotlin theme={"dark"}
fun evaluate(payload: Any): Int {
    return when (payload) {
        is String -> payload.length // 'payload' is smart-cast to String
        is List<*> -> payload.size  // 'payload' is smart-cast to List
        else -> 0
    }
}
```

**2. Smart Cast Guarantees and Mutable Variables**
Smart casting inside a `when` block relies on the compiler's ability to guarantee that the subject variable cannot change between the type check and its usage.

* It succeeds for local `val` variables, function parameters, and `val` properties of the same module without custom getters.
* It succeeds for local `var` variables, provided the compiler can guarantee they are not modified between the type check and the usage, and they are not captured by a lambda that modifies them.
* If the compiler cannot guarantee immutability (e.g., for mutable properties, open properties, or properties with custom getters), the `when` expression and the `is` check still compile and execute perfectly fine. It is only the *smart cast* that is denied. Compilation will only fail if the developer subsequently attempts to invoke methods or properties specific to the asserted type without manually casting it (`as`).

**3. Inline Variable Declaration**
To strictly scope the subject and guarantee immutability for smart casting, Kotlin allows declaring a local `val` directly inside the `when` subject parenthesis. Kotlin's grammar fully supports explicit type annotations for this inline variable, though the type can also be inferred.

```kotlin theme={"dark"}
interface Response
class Success(val data: String) : Response
class Error(val exception: Exception) : Response

fun executeRequest(): Response = Success("Data loaded")

fun process() {
    when (val response: Response = executeRequest()) {
        is Success -> println(response.data)      // 'response' is scoped only to the when block
        is Error -> println(response.exception)   // 'response' is smart-cast to Error
        else -> println("Unknown response")
    }
}
```

**4. Exhaustiveness**
The compiler enforces exhaustiveness for all `when` expressions (where the result is assigned or returned). Since Kotlin 1.7, exhaustiveness is also strictly enforced for `when` *statements* if the subject is a `sealed` class, `sealed` interface, `enum`, or `Boolean`.

An `else` branch is required unless the provided branches exhaustively cover all possible types:

* **Open Types:** For open types (like standard non-sealed classes), an `else` branch is generally required when the construct is used as an expression. The Kotlin compiler does not perform logical exhaustiveness checking for complementary checks (e.g., `is String` and `!is String`). However, if the subject is of a non-nullable type, providing an `is Any` branch *does* satisfy the compiler's exhaustiveness requirement, and no `else` branch is needed (though the compiler will emit a warning that the check is always true).
* **Sealed Types:** For `sealed` classes or `sealed` interfaces, the compiler resolves all possible subtypes at compile time. If all subtypes are checked using `is`, the `else` branch is safely omitted.

```kotlin theme={"dark"}
sealed class State
class Loading : State()
class Loaded(val data: String) : State()

fun getState(): State = Loading()

fun render() {
    // Exhaustive expression: No 'else' branch needed because State is sealed
    val uiText = when (val currentState = getState()) {
        is Loading -> "Please wait..."
        is Loaded -> currentState.data // Smart-cast to Loaded
    }
}
```

**5. Evaluation Order**
Branches are evaluated sequentially from top to bottom. The construct terminates evaluation as soon as the first matching `is` or `!is` condition is met. If a subject implements multiple interfaces or inherits from multiple classes checked in the block, only the first matching branch executes.

<div
  style={{ 
display: "flex", 
justifyContent: "space-between", 
alignItems: "center", 
maxWidth: "754px", 
padding: "1rem 0",
marginBottom: "24px"
}}
>
  <span style={{ fontWeight: "bold", fontSize: "1.25rem", color: "var(--tw-prose-headings)", fontFamily: "Inter, ui-sans-serif, system-ui, sans-serif" }}>Tired of Poor Kotlin Skills? Fix That With Deep Grasping!</span>

  <a
    href="https://syntblaze.com"
    target="_blank"
    style={{ 
  marginLeft: "24px",
  textDecoration: "none", 
  backgroundColor: "#007AFF",
  color: "#ffffff", 
  padding: "6px 16px", 
  borderRadius: "16px",
  fontSize: "0.9rem",
  fontWeight: "600",
  textAlign: "center",
  transition: "background-color 0.2s ease"
}}
  >
    Learn More
  </a>
</div>

<div style={{ display: "flex", gap: "12px", flexWrap: "wrap" }}>
  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/skill-tracking.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=b9b0305c93bb501c9e767b5c76c88835" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/skill-tracking.png" />

  <img src="https://mintcdn.com/syntblazellc/23tyuOzaWS88qFlc/images/nuggets.png?fit=max&auto=format&n=23tyuOzaWS88qFlc&q=85&s=c86c80197299762989e9b882419b2109" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/nuggets.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/bite-sized-exercises.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=a65f9a38c37ff28ab73ed783c53c60e3" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/bite-sized-exercises.png" />
</div>

<div style={{ display: "flex", gap: "12px", flexWrap: "wrap", marginTop: "12px" }}>
  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/mastery-chain.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=748a1763454713e679260fbb95f154a2" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/mastery-chain.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/element-previews.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=242f61448ff5dd6deaaab2dccc13b507" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/element-previews.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/element-explanations.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=cf0fc1c31f9cd0fc26716781be05fbc9" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/element-explanations.png" />
</div>
