PC パソコン

Solutions for Kotlin “Cannot infer a type for this parameter”

When writing code in Kotlin, you may encounter an error called “Cannot infer a type for this parameter”.

This error occurs when the Kotlin compiler cannot determine the type of a parameter in a lambda expression, callback, or similar construct.

Kotlin performs type inference in many situations, so you can normally omit parameter types. However, if the surrounding information is not sufficient to determine a single type, you need to specify the type explicitly.

This article introduces the main causes of the “Cannot infer a type for this parameter” error in Kotlin and the basic ways to resolve it.

What Is “Cannot infer a type for this parameter”?

“Cannot infer a type for this parameter” is an error indicating that the compiler cannot infer the type of a parameter.

It occurs particularly often with parameters in lambda expressions.

val action = { value ->
    println(value)
}

In this code, there is no information that allows the compiler to determine what type value is.

Therefore, the compiler may be unable to infer the type of value, resulting in an error.

In such cases, explicitly specify the parameter type.

val action = { value: Int ->
    println(value)
}

By explicitly specifying that value is an Int, the compiler can determine its type.

Cause 1: The Parameter Type of a Lambda Expression Is Unknown

The most basic cause is that there is not enough information to infer the type of a parameter in a lambda expression.

val printer = { item ->
    println(item)
}

In this case, the compiler cannot determine whether item is a String, an Int, or some other type.

You can resolve the issue by explicitly specifying the parameter type.

val printer = { item: String ->
    println(item)
}

In this way, write : TypeName after the parameter in the lambda expression.

Cause 2: The Type of the Variable to Which the Lambda Expression Is Assigned Is Not Specified

Even without directly specifying the parameter type of the lambda expression, the type may be inferred by specifying a function type for the variable to which it is assigned.

val printer: (String) -> Unit = { item ->
    println(item)
}

In this case, because printer is known to have the function type (String) -> Unit, item in the lambda expression is inferred as a String.

If you do not need to write the type directly in the lambda expression each time, you can also use this method.

Cause 3: The Element Type of a Collection Is Unclear

When using map, filter, or similar functions on a collection, if the type of the original collection is unclear, the parameter type of the lambda expression may also be impossible to determine.

val items = emptyList()

items.forEach { item ->
    println(item)
}

With code like this, emptyList() alone does not determine the element type, so type inference may also fail in subsequent processing.

Explicitly specify the collection type.

val items: List<String> = emptyList()

items.forEach { item ->
    println(item)
}

This causes item to be inferred as a String.

Cause 4: The Type Cannot Be Inferred with emptyList, listOf, or Similar Functions

When creating an empty collection, there are no elements, so the compiler may be unable to determine the element type.

val values = emptyList()

In such cases, explicitly specify the type argument.

val values = emptyList<String>()

Alternatively, specify the type on the variable side.

val values: List<String> = emptyList()

Making the collection type clear also makes it easier to infer the parameter types of lambda expressions that use the collection.

Cause 5: The Type Argument of a Generic Function Cannot Be Inferred

When using a generic function, if there is insufficient information at the call site, the type argument cannot be determined, and as a result, the parameter type of a lambda expression may also be impossible to infer.

fun <T> process(action: (T) -> Unit) {
}

fun main() {
    process { value ->
        println(value)
    }
}

In this example, there is no information that allows the compiler to determine what type T is.

In this case, explicitly specify the type argument.

fun main() {
    process<String> { value ->
        println(value)
    }
}

This determines that T is a String, and value is also treated as a String.

Cause 6: The Lambda Expression Type Is Ambiguous in an Overloaded Function

When multiple functions have the same name and each accepts a different function type, the lambda expression alone may not provide enough information to determine which overload should be used.

fun execute(action: (Int) -> Unit) {
    action(1)
}

fun execute(action: (String) -> Unit) {
    action("Hello")
}

In such cases, depending on how the function is called, the parameter type of the lambda expression may not be inferred.

You can narrow down the candidates by explicitly specifying the parameter type.

execute { value: Int ->
    println(value)
}

This makes it clear that the function accepting (Int) -> Unit should be used.

Cause 7: The Callback Type Is Not Defined

When creating custom callback processing, if the callback type is unclear, the type of the parameter used within it may not be inferred.

val callback = { result ->
    println(result)
}

In this case as well, there is no information that allows the compiler to determine the type of result.

Specifying the function type resolves the issue.

val callback: (Boolean) -> Unit = { result ->
    println(result)
}

This causes result to be inferred as a Boolean.

Cause 8: The Return Type of a Function or the Type of a Variable Is Ambiguous

The cause may not be the lambda expression where the error is displayed, but rather an ambiguous type in the function or variable that receives the lambda expression.

For example, when using the return value of a function and passing it to another process, if the type is not clear at an earlier stage, type inference may also fail in a subsequent lambda expression.

When “Cannot infer a type for this parameter” is displayed, it is important to check not only the parameter at the error location but also the types of the function, variable, and collection that receive or relate to the lambda expression.

Resolve the Error by Explicitly Specifying the Lambda Parameter Type

The most direct solution is to specify the type of the lambda parameter that the compiler cannot determine.

val action = { value: Int ->
    println(value)
}

If there are multiple parameters, you can specify the type of each one.

val action = { name: String, age: Int ->
    println("$name: $age")
}

By explicitly specifying the required types, you can provide the compiler with the necessary information without relying on type inference.

Resolve the Error by Explicitly Specifying the Function Type

Instead of specifying the type on the parameter side of the lambda expression, you can also specify a function type for the variable or property.

val action: (Int) -> Unit = { value ->
    println(value)
}

In this case, the lambda parameter value is automatically inferred as an Int.

This method also makes it easier to understand what kind of processing the entire lambda expression represents.

Resolve the Error by Explicitly Specifying the Generic Type

If a generic function or collection is the cause, explicitly specifying the type argument may resolve the issue.

val values = mutableListOf<String>()

For a generic function, you can specify the type as follows.

process<String> { value ->
    println(value)
}

When there is insufficient information for type inference, explicitly specifying the type at one point may allow the compiler to infer the types that follow.

When You Can Use it

When a lambda expression has one parameter and its type can be inferred from the surrounding context, you can omit the parameter name and use it.

val names = listOf("Taro", "Jiro")

names.forEach {
    println(it)
}

In this case, because names is a List<String>, it is inferred as a String.

However, if the underlying type is unclear, using it does not resolve the type inference problem itself.

Points to Check When “Cannot infer a type for this parameter” Appears

When “Cannot infer a type for this parameter” appears, check whether the compiler has enough information to determine the type of the parameter.

  • Is the parameter type of the lambda expression omitted?
  • Is a function type specified for the variable to which the lambda expression is assigned?
  • Is the element type of the collection clear?
  • Are type arguments missing from emptyList(), mutableListOf(), or similar functions?
  • Is there enough information to infer the type argument of the generic function?
  • Are multiple function type candidates present because of overloading?
  • Is the callback type clearly defined?
  • Has type information been lost in processing before the error location?

Rather than fixing only the parameter where the error is displayed, checking where the value comes from and which function or variable receives it makes it easier to identify the cause.

Summary

Kotlin’s “Cannot infer a type for this parameter” is an error that appears when the compiler cannot infer the type of a parameter in a lambda expression, callback, or similar construct.

Typical causes include an unknown lambda parameter type, an undetermined collection or generic type, and multiple candidates caused by overloading.

Basically, the error can be resolved by explicitly specifying the lambda parameter type, specifying a function type for the variable, or explicitly specifying the type arguments of collections or generics.

It is also important to check not only the location where the error is displayed but also the function or variable that receives the lambda expression and the type of the original collection.

When “Cannot infer a type for this parameter” appears, check “where the information needed by the compiler to determine the parameter type is located” and explicitly provide any missing type information. This makes it easier to resolve the cause.