janvladimirmostert
02/26/2023, 10:28 PMinterface UserRepository {
sealed interface UserRepositoryResult {
object UserNotFound : UserRepositoryResult
object InvalidId : UserRepositoryResult
}
sealed interface FindUserByIdResult : UserRepositoryResult {
class Success(val user: User) : FindUserByIdResult
}
fun findUserById(id: User.Id): FindUserByIdResult
sealed interface DeleteUserByIdResult : UserRepositoryResult {
object Success : DeleteUserByIdResult
}
fun deleteUserById(id: User.Id): DeleteUserByIdResult
The above compiles, but when adding a when
around the result of findUserById
, it only looks for the Success
branch
when (this@UserRepository.findUserById(0)) {
is UserRepository.FindUserByIdResult.Success -> TODO()
}
it's only expecting the one branch
nesting it doesn't make a difference either
sealed interface UserRepositoryResult {
object UserNotFound : UserRepositoryResult
object InvalidId : UserRepositoryResult
sealed interface FindUserByIdResult : UserRepositoryResult {
class Success(val user: User) : FindUserByIdResult
}
sealed interface DeleteUserByIdResult : UserRepositoryResult {
object Success : DeleteUserByIdResult
}
}
fun findUserById(id: User.Id): UserRepositoryResult.FindUserByIdResult
fun deleteUserById(id: User.Id): UserRepositoryResult.DeleteUserByIdResult
is there a way around this other than copying and pasting UserNotFound and InvalidId into both sealed interfaces?Edwar D Day
02/27/2023, 7:16 AMsealed interface UserRepositoryResult<out T> {
object UserNotFound : UserRepositoryResult<Nothing>
object InvalidId : UserRepositoryResult<Nothing>
data class Success<T>(val data: T): UserRepositoryResult<T>
fun findUserById(id: User.Id): UserRepositoryResult<User>
fun deleteUserById(id: User.Id): UserRepositoryResult<Unit>
}
janvladimirmostert
02/27/2023, 8:05 AMfun dosSomethingElseById(id: User.Id): DoSomethingElseByIdResult
has more possible errors, then that error should be inside DoSomethingElseByIdResult
including the InvalidId
and UserNotFound
errors
Sounds like a limitation of sealed interfaces / classesEdwar D Day
02/27/2023, 8:22 AMUserNotFound
and InvalidId
everywhere, you define them in a separate sealed interface, which extends the concrete result interfaces:
sealed interface UserRepositoryResult {
sealed interface GenericErrorResult: FindUserByIdResult, DeleteUserByIdResult{
object UserNotFound : GenericErrorResult
object InvalidId : GenericErrorResult
}
sealed interface FindUserByIdResult : UserRepositoryResult {
class Success(val user: User) : FindUserByIdResult
}
sealed interface DeleteUserByIdResult : UserRepositoryResult {
object Success : DeleteUserByIdResult
}
}
fun findUserById(id: User.Id): UserRepositoryResult.FindUserByIdResult
fun deleteUserById(id: User.Id): UserRepositoryResult.DeleteUserByIdResult
janvladimirmostert
02/27/2023, 9:36 AM