Kotlin force nullable generic type into a non-nullable of the same generic type?
I created a minimal example which achieves what you want:
fun <T: Any> test(t: T?): T {
// ...
return t as T
}
You define an upper bound Any
for T
so it cannot be null
. For the parameter t
you use the type T?
. In the end you return t
casted to T
.
Examples:
val a: String = test("Hello")
val b: String = test(null)
AwaitilityKtUntilFunCondition
can be made contravariant (so AwaitilityKtUntilFunCondition<T>
is a subtype of AwaitilityKtUntilFunCondition<T?>
), and this modification of your gist seems to satisfy the requirements:
// Fake Awaitility DSL
data class AwaitilityKtUntilFunCondition<out T>(val factory: ConditionFactory, val fn: () -> T)
infix fun <T : Any> AwaitilityKtUntilFunCondition<T?>.has(pred: T.() -> Boolean): T = factory.until(fn) { t: T? ->
if (t == null) {
false
} else {
pred(t)
}
}!!
class ConditionFactory {
fun <T : Any?> until(supplier: () -> T, predicate: (T) -> Boolean): T {
val result = supplier()
return if (predicate(result)) {
result
} else {
throw IllegalArgumentException("Supplied value is not matching predicate")
}
}
}
class Await {
infix fun <T> untilCallTo(supplier: () -> T): AwaitilityKtUntilFunCondition<T> {
val conditionFactory = ConditionFactory()
return AwaitilityKtUntilFunCondition(conditionFactory, supplier)
}
}
// Example
data class Data(var state: String)
interface DataRepository<T> {
fun loadData(): T
}
val nullableDataRepository: DataRepository<Data?> = TODO()
val nonNullableDataRepository: DataRepository<Data> = TODO()
// Both of these compile
val data1: Data = Await() untilCallTo { nonNullableDataRepository.loadData() } has {
state == "something"
}
val data2: Data = Await() untilCallTo { nullableDataRepository.loadData() } has {
state == "something"
}