Reputation: 774
Given this code:
// Can generic type parameter be inferred?
class Foo<T> {
fun consume(p: T) {
println("slurp $p")
}
}
//region
abstract class ATestsOfFoo<U: Foo<T>, T>(private val foo: U) {
fun test1() {
foo.consume(someT())
}
abstract fun someT(): T
}
class TestsOfFoo(foo: Foo<String>): ATestsOfFoo<Foo<String>, String>(foo) {
override fun someT(): String {
return "Hello"
}
}
val testsOfFoo = TestsOfFoo(Foo())
testsOfFoo.test1()
//endregion
I'm looking for a way to infer T
type parameter from U
.
Said differently, I'd like to be able to write the following line without repeating String
as the type parameter:
...
// This is an example of what I'd like to be able to write, it does not work
class TestsOfFoo(foo: Foo<String>): ATestsOfFoo<Foo<String>>(foo) {
...
Is there a way to do so?
If not, is there a conceptual flaw that would forbid us to safely infer T
from U
?
P.S:
I know we could simplify ATestsOfFoo
like this:
abstract class ATestsOfFoo<T>(private val foo: Foo<T>) {
...
however I'm not looking for that, conceptually ATestsOfFoo
operates on Foo<T>
, I'd like to keep that information in type parameters.
Upvotes: 2
Views: 2195
Reputation: 351
In short, no, Kotlin will not infer the type based on the super constructor call's argument types like this. Kotlin's type inference only supports local variable inference and function signature type inference.
You can read more about that in the Kotlin spec (https://kotlinlang.org/spec/type-inference.html)
I'm not sure if there's a conceptual flaw here and I am not that experienced in type systems, but I know this is inferable with TypeScript's type system but that's because TypeScript's constrait solver and type checker can work with conditional types and default types for generics, which is not a language feature Kotlin has.
interface Foo<T> {
consume(p: T): void
}
interface FooImpl1<U extends Foo<T>, T = U extends Foo<infer X> ? X : never> {
test(foo: U): T
}
class FooImpl implements FooImpl1<Foo<string>> {
test(foo: Foo<string>): string { ... }
}
In conclusion; with the current type system Kotlin has we have no way to express this. Unfortunately you will just have to repeat the types.
Upvotes: 3