skip to content

What does the type `T & Any` mean in Kotlin, and what problem does it solve?

level: juniorimportance: should knowfreq 35%

answer

  1. T & Any = T but guaranteed non-null
  2. Intersection with Any strips nullability
  3. Only valid when T's bound is nullable (default Any?)
  4. Stable since Kotlin 1.7
  5. Main purpose: Java @NotNull interop overrides

basics

~10 s

T & Any means "the type T, but guaranteed not null." If a generic type T could be null, writing T & Any forces it to be a non-null version of that type.

solid answer

~50 s

`T & Any` is Kotlin's definitely-non-null type notation, stabilized in Kotlin 1.7. When a generic type parameter has a nullable upper bound (e.g. `<T>` with implicit bound `Any?`, or `<T : Comparable<T>?>`), the parameter itself is nullable, so you cannot guarantee a non-null value of it. `T & Any` is an intersection of `T` with `Any` (the non-nullable root of every type), which strips nullability: the result is always non-null no matter what `T` is bound to. Its main use is at the Java interop boundary: when you override a Java method whose return is annotated `@NotNull` but whose Java signature involves a nullable type variable, `T & Any` lets the Kotlin override declare a precise non-null return type. You can only write `T & Any` where `T` is a type parameter with a nullable bound.

code

kotlin · 8 lines
kotlin
// T has the default upper bound Any? (nullable)
fun <T> elvisLike(x: T, y: T & Any): T & Any = x ?: y

fun main() {
    val a: Int = elvisLike(5, 6)        // T = Int, fine
    val b: Int = elvisLike(null, 12)    // T = Int?, result still non-null Int
    println("$a $b")
}

go deeper

for a junior

Can state that T & Any is 'T but not null' and recognize the syntax.

for a middle

Explains it as an intersection with Any that strips nullability and knows it needs a nullable bound.

for a senior

Connects it to the Java @NotNull interop motivation and the default Any? bound on type parameters.

for a principal

Frames it within Kotlin's type lattice (intersection types, nullability as part of the type) and can reason about when the compiler warns or rejects it.

## The problem: generics with nullable bounds Every Kotlin type parameter has an **upper bound**. If you don't write one, the default is `Any?` (nullable). So: ```kotlin fun <T> firstOrNull(list: List<T>): T? = list.firstOrNull() ``` Here `T` could be substituted with `String`, but also with `String?`. Because the bound is `Any?`, the compiler treats a bare `T` as **possibly nullable** — you can't promise a value of type `T` is non-null. Sometimes you genuinely have a non-null value but the type system won't let you express it cleanly. Before Kotlin 1.7 the only workaround was `@Suppress` casts or wrapper bounds. ## The solution: `T & Any` `T & Any` is the **definitely-non-null** notation (stable since Kotlin 1.7). It is an **intersection type** of `T` and `Any`: - `Any` is the root of all **non-nullable** types (its nullable counterpart `Any?` is the root of everything). - Intersecting any type with `Any` removes the nullability: `String? & Any` is `String`, `T? & Any` is the non-null `T`. So `T & Any` is always a non-null type, regardless of how `T` is instantiated. ```kotlin fun <T> elvisLike(x: T, y: T & Any): T & Any = x ?: y ``` Here the result is guaranteed non-null even though `T` itself may be nullable. ## Where you can write it You may only use `T & Any` when `T` is a **type parameter whose upper bound is nullable** (the default `Any?`, or an explicit `Something?`). Writing `T & Any` on a parameter with a non-nullable bound is redundant and the compiler reports a warning. ## Primary use: Java interop The feature exists mainly to let Kotlin **override Java methods precisely**. If a Java generic method is annotated `@NotNull` on a return that is a type variable, the Kotlin override can declare `T & Any` so callers see a non-null type instead of a platform type. This is discussed in the follow-up questions. ## Recap of the keywords/operators involved - `&` — the intersection-type operator, used **only** in this definitely-non-null form. - `Any` / `Any?` — non-nullable vs nullable roots. - upper bound — the declared supertype of a type parameter.

  • Since which Kotlin version is `T & Any` stable, and was there an earlier form?
    It was previewed in Kotlin 1.6 (with `-language-version 1.7`) and stabilized in Kotlin 1.7. There was no earlier sanctioned syntax; people used unchecked casts.
  • What happens if you write `T & Any` when `T`'s bound is already non-null (e.g. `T : Any`)?
    It is redundant — the compiler emits a warning because the type is already non-null, so the intersection adds nothing.

Any? is 'a box that may be empty'; intersecting with Any is like stamping 'guaranteed full' on the box.

saying these in an interview costs you the question

  • Thinking `T & Any` means 'T and also some Any object' rather than a nullability-stripping intersection
  • Believing it works for any T regardless of bound
  • Confusing it with `T!!` (not-null assertion) which is a runtime operator, not a type
  • Saying it changes runtime behavior — it is a compile-time type, erased at runtime

context