
Learn through the super-clean Baeldung Pro experience:
>> Membership and Baeldung Pro.
No ads, dark-mode and 6 months free of IntelliJ Idea Ultimate to start with.
Last updated: August 30, 2024
When working with Kotlin, we might encounter an error that reads, “Type mismatch: inferred type is Unit but Void was expected”. This error can be confusing, especially for those transitioning from Java.
In this quick tutorial, we’ll examine this error in more detail and discuss how to resolve it.
First, let’s reproduce this error through an example:
fun customGreetingVoid(name: String, greeting: (String) -> Void) = greeting(name)
Here, we created a function with two arguments:
The customGreetingVoid() implementation passes name to the greeting() function. Therefore, it allows us to customize the greeting‘s implementation and perform the dynamic “greeting” operation.
Next, let’s see how to use this function by an example:
customGreetingVoid("Tom Hanks"){
log.info("Hi $it, how do you do?")
}
In the above code, we pass the String “Tom Hanks“ as the name parameter and a lambda expression as the functional parameter. The lambda expression outputs a customized greeting message using log.info(), where log is an instance of org.slf4j.Logger.
Further, log.info() returns void:
public void info(String msg);
In other words, log.info() doesn’t return anything. The greeting functional parameter requires (String) -> Void. So, we think the types match, and we expect to see the output like this:
... [INFO] Hi Tom Hanks, how do you do?
However, the code doesn’t compile. When we attempt to compile it, we see the compiler error:
Kotlin: Type mismatch: inferred type is Unit but Void was expected
Some of us may consider asking the lambda to return null:
customGreetingVoid("Kai"){
log.info("Hello $it")
null
}
But this code doesn’t compile either since a non-null type is required:
Kotlin: Null can not be a value of a non-null type Void
Next, let’s understand what causes this compilation error and see how to fix it.
As mentioned earlier, our lambda expression uses a Java method, log.info(), that returns void. On the other hand, the error message explicitly mentions the mismatched types: Unit and Void.
So, let’s quickly understand what void, Void, and Unit are:
Next, let’s discuss the cause of the compiler error.
First, let’s look at the functional parameter definition — greeting: (String) -> Void.
We intend to have a function that takes a String as the parameter and returns nothing. However, the return type we used is Void, which is a regular Java class:
public final class Void {
public static final Class<Void> TYPE = (Class<Void>) Class.getPrimitiveClass("void");
/*
* The Void class cannot be instantiated.
*/
private Void() {}
}
In other words, this parameter expects a function that returns an instance of Void, although Void is only for reflection usage and cannot be instantiated due to the private constructor.
log.info() is a Java method call in our lambda expression that returns void (nothing). We’ve learned that in Kotlin, Unit represents Java’s void keyword. Therefore, our lambda expression returns Unit.
Thus, the cause of the compiler error is clear: we passed a function (lambda expression) that returns Unit as a parameter that requires a Void instance as the return type.
Fixing the problem becomes a simple task since we understand the cause of the error. Changing the functional parameter’s return type from Void to Unit resolves the error:
fun customGreetingUnit(name: String, greeting: (String) -> Unit) = greeting(name)
Now, if we run the code with a similar lambda:
customGreetingUnit("Tom Cruise") {
log.info("Hi $it, how are you doing?")
}
We see the expected output:
12:40:28.618 [main] INFO ... - Hi Tom Cruise, how are you doing?
So, the problem is solved.
In this article, we’ve discussed the compiler error, “inferred type is Unit but Void was expected” and how to fix it. This error in Kotlin arises from misunderstandings about Kotlin’s type system, particularly regarding Unit.