Jackson Chengalai
Jackson Chengalai

Reputation: 3937

Type inference failed: Not enough information to infer parameter T Kotlin

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

Answers (3)

V-master
V-master

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

s1m0nw1
s1m0nw1

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

yole
yole

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

Related Questions