This seems to be an issue with Kotlin's type inference (though whether it is a bug or by design, I don't know). For example, if the types are explicit, this does not compile:
check<String, Int>("Hello", String::length, "banana")
It is probably designed to work like Java's generic method type inference, which allows this because the compiler infers a common super-type of R
and T
for both parameters. See Why doesn't type argument inference fail when I provide inconsistent method arguments?
According to the post above, in Java 5, 6, and 7 you could probably declare it like
fun <T, R, R1: R> check(thing: T, property: KProperty1<T, R>, value: R1) =
property.get(thing) == value
and the call with inconsistent params would not compile (I haven't tried it). However, this was considered a bug and in Java 8 the call with inconsistent params still compiles (I tried it).
In any case, you could wrap it in a class to avoid the inference and tie the type parameters together:
class Checker<T, R>(val property: KProperty1<T, R>) {
fun check(thing: T, value: R) =
property.get(thing) == value
}
assertTrue(Checker(String::length).check("Hello", 5))
// does not compile
assertTrue(Checker(String::length).check("Hello", "banana"))