Skip to main content

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.

Type inference is a compiler feature in Kotlin that automatically deduces the static type of a variable, property, function return, or generic argument from its context and initialization expression at compile time. This mechanism allows developers to omit explicit type declarations while maintaining the strict type safety of a statically typed language.

Variable and Property Declarations

When declaring a variable using the val (read-only) or var (mutable) keywords, the Kotlin compiler analyzes the right-hand side of the assignment. The type of the evaluated expression becomes the permanent static type. While local variables require an immediate initialization expression for type inference, class-level or top-level properties can also infer their type from a custom getter’s return value without an explicit initializer.
// Top-level or class-level property inferred from getter
val isReady get() = true // Inferred as kotlin.Boolean

fun initializeSystem() {
    // Local variable inferred from immediate initialization
    val inferredString = "System initialized" // Inferred as kotlin.String

    // Deferred initialization requires explicit type declaration
    var deferredCounter: Int
    deferredCounter = 0
}

Single-Expression Functions

The compiler can infer the return type of a function if it is written as a single expression using the assignment operator (=) instead of a block body. The inferred return type matches the static type of the evaluated expression.
// Explicit return type
fun sumExplicit(a: Int, b: Int): Int = a + b

// Inferred return type
fun sumInferred(a: Int, b: Int) = a + b // Inferred as kotlin.Int

Generic Type Arguments

Kotlin infers generic type parameters based on the arguments provided to a function or constructor. If the type can be deduced from the passed values, explicit type arguments inside angle brackets (<T>) can be omitted.
// Explicit generic type
val explicitList: List<Int> = listOf<Int>(1, 2, 3)

// Inferred generic type
val inferredList = listOf(1, 2, 3) // Inferred as List<Int>

Lambda Parameters

When a lambda expression is passed to a higher-order function, the compiler infers the types of the lambda parameters based on the expected functional interface or the function signature.
val numbers = listOf(1, 2, 3)

// Parameter 'it' is implicitly inferred as kotlin.Int based on List<Int>.map signature
val doubled = numbers.map { it * 2 } 

Static Type Immutability

Kotlin remains strictly statically typed regardless of inference. Once the compiler infers a type, it is permanently bound to that identifier within its scope. Attempting to reassign a var to a value of a non-conforming type results in a Type mismatch compilation error.
fun updateStatus() {
    var statusCode = 200 // Inferred as kotlin.Int
    statusCode = 404     // Valid: Reassignment of the same type
    
    // statusCode = "OK" // Compilation Error: Type mismatch. Required Int, found String
}

Literal Type Resolution

The compiler applies specific rules when inferring types from numeric literals:
  • Integers: Whole numbers are inferred as Int by default. If the value exceeds Int.MAX_VALUE, it is automatically inferred as Long.
  • Longs: Explicitly appending an L suffix forces inference to Long.
  • Floating-point: Decimal numbers are inferred as Double by default.
  • Floats: Explicitly appending an f or F suffix forces inference to Float.
val defaultInt = 42           // Inferred as Int
val largeInt = 3000000000     // Inferred as Long (exceeds Int.MAX_VALUE)
val explicitLong = 42L        // Inferred as Long
val defaultDouble = 3.14      // Inferred as Double
val explicitFloat = 3.14f     // Inferred as Float
Master Kotlin with Deep Grasping Methodology!Learn More