Reputation: 3937
I am using a sealed class to return data from network. but when i am building the project i am getting the following error
Type inference failed: Not enough information to infer parameter T in fun error(errorMessage: String, error: Throwable): State Please specify it explicitly.
What am i missing here?
Here is the code
suspend fun getdataFromApi(context: Context?, token: String?): State<ScheduleReminderListResponse> =
withContext(schedulerProvider.io)
{
try {
val list = network.getScheduleReminderList(token).await()
schedeleReminderListLocalDao.insertAll(list)
return@withContext State.success(list)
} catch (e: Exception) {
return@withContext State.error( e.message ?: "Unknown Error", e )
}
}
sealed class State<T> {
class Loading<T>: State<T>()
data class Error<T>(val errorMessage: String?, val error: Throwable): State<T>()
data class Success<T>(var data: T) : State<T>()
companion object {
fun <T> loading(): State<T> =
Loading()
fun <T> error(errorMessage: String, error: Throwable): State<T> =
Error(errorMessage, error)
fun <T> success(data: T): State<T> =
Success(data)
}
}
Upvotes: 3
Views: 14238
Reputation: 2177
In oposition to @s1m0nw1 answer, if you want to keep the type parameter in the State
model (so that return values are nice looking and type-safe) you could consider marking T
as out
and use Nothing
in sub-classes that do not use it
sealed class State<out T> {
object Loading: State<Nothing>()
data class Error(val errorMessage: String?, val error: Throwable): State<Nothing>()
data class Success<T>(var data: T): State<T>()
companion object {
fun <T> loading(): State<T> = Loading
fun <T> error(errorMessage: String, error: Throwable): State<T> = Error(errorMessage, error)
fun <T> success(data: T): State<T> = Success(data)
}
}
that way your example method will stay the same nad you do not need to perform unsafe casts
Upvotes: 1
Reputation: 82117
In this line State.error( e.message ?: "Unknown Error", e )
the compiler does not know what T
should be. If you compare it with success
, you will see that you explicitly provide an argument of T
which the compiler uses to infer the type.
You can specify it like this when calling error:
State.error<TYPE_OF_SCHEDULE_REMINDER_LIST>( e.message ?: "Unknown Error", e )
Since you're not using T
in Error
, you probably want to consider removing it entirely from the sealed class and only use it where it makes sense.
sealed class State {
object Loading : State()
data class Error(val errorMessage: String?, val error: Throwable) : State()
data class Success<T>(var data: T) : State()
companion object {
fun loading(): State = Loading
fun error(errorMessage: String, error: Throwable): Error =
Error(errorMessage, error)
fun <T> success(data: T): Success<T> = Success(data)
}
}
Upvotes: 6
Reputation: 97338
The Error
data class defines the T
type parameter but does not use it in any way. Therefore, when you create an Error
instance, there is no way for the compiler to infer what type should be used for T.
To fix this, change the definition of State
and Error
so that they don't have a type parameter.
Upvotes: 2