Sealed Result Hierarchies
Custom result types.
Sealed Result Hierarchies is a free Kotlin Academy lesson on CoddyKit. This is lesson 3 of 4. Any 3 lessons of this learning path are free to read in full — after that, CoddyKit PRO unlocks every lesson, plus hands-on practice with a built-in code editor and a 24/7 AI tutor. It is part of the Kotlin Academy learning path, and your progress syncs across the web and the CoddyKit app. The Kotlin Academy course includes 4 lessons in total.
Beyond the Built-in Result
Kotlin's Result only carries an exception on failure. Often you want richer, typed error information. A sealed class hierarchy lets you model exactly the outcomes your domain has.
A Sealed Outcome
Define a sealed type with success and error subclasses. The compiler knows all cases, enabling exhaustive handling.
sealed class Outcome<out T> {
data class Ok<T>(val value: T) : Outcome<T>()
data class Err(val message: String) : Outcome<Nothing>()
}
fun main() {
val r: Outcome<Int> = Outcome.Ok(5)
println(r)
}Exhaustive when
Because the type is sealed, a when over it needs no else, and the compiler enforces handling every case.
sealed class Outcome<out T> {
data class Ok<T>(val value: T) : Outcome<T>()
data class Err(val message: String) : Outcome<Nothing>()
}
fun describe(o: Outcome<Int>) = when (o) {
is Outcome.Ok -> "value " + o.value
is Outcome.Err -> "error " + o.message
}
fun main() {
println(describe(Outcome.Ok(9)))
println(describe(Outcome.Err("boom")))
}Typed Error Variants
Model distinct failure kinds as separate subclasses, each carrying relevant data. This beats a single opaque exception.
sealed class Fetch<out T> {
data class Success<T>(val data: T) : Fetch<T>()
data class NotFound(val id: Int) : Fetch<Nothing>()
data class Network(val code: Int) : Fetch<Nothing>()
}
fun main() {
val r: Fetch<String> = Fetch.NotFound(42)
println(r)
}Handling Each Variant
A when can react specifically to each error type, with full data available for each branch.
sealed class Fetch<out T> {
data class Success<T>(val data: T) : Fetch<T>()
data class NotFound(val id: Int) : Fetch<Nothing>()
data class Network(val code: Int) : Fetch<Nothing>()
}
fun handle(f: Fetch<String>) = when (f) {
is Fetch.Success -> "data: " + f.data
is Fetch.NotFound -> "missing id " + f.id
is Fetch.Network -> "net error " + f.code
}
fun main() {
println(handle(Fetch.Network(503)))
}The Nothing Trick
Error variants that hold no success value use Outcome<Nothing>. Since Nothing is a subtype of every type and the generic is out, an error fits any Outcome<T>.
sealed class Res<out T> {
data class Ok<T>(val v: T) : Res<T>()
object Empty : Res<Nothing>()
}
fun get(flag: Boolean): Res<String> =
if (flag) Res.Ok("hi") else Res.Empty
fun main() {
println(get(false))
}Object for Stateless Cases
If an error variant carries no data, declare it as an object singleton instead of a class.
sealed class Login {
data class Success(val user: String) : Login()
object WrongPassword : Login()
object Locked : Login()
}
fun main() {
val r: Login = Login.WrongPassword
println(r === Login.WrongPassword)
}Returning the Hierarchy
Functions return the sealed type; callers must address every outcome, eliminating forgotten error paths.
sealed class Parsed {
data class Num(val value: Int) : Parsed()
data class Bad(val input: String) : Parsed()
}
fun parse(s: String): Parsed {
val n = s.toIntOrNull()
return if (n != null) Parsed.Num(n) else Parsed.Bad(s)
}
fun main() {
when (val r = parse("x")) {
is Parsed.Num -> println(r.value)
is Parsed.Bad -> println("bad: " + r.input)
}
}Sealed vs Built-in Result
Use the built-in Result for quick, exception-based capture. Use a custom sealed hierarchy when you need multiple typed error cases with domain-specific data and exhaustive handling.
Designing the Hierarchy
Good sealed result design:
- One success variant carrying the payload
- One subclass per meaningful failure mode
out Tvariance withNothingfor error-only cases
Compiler as Safety Net
The biggest win: when you add a new variant later, every non-exhaustive when becomes a compile error, pointing you to each place that must handle it. Errors cannot silently slip through.
Quick Check
Test your understanding of sealed result hierarchies.
Recap
You built sealed result hierarchies:
- Success plus typed error variants
- Exhaustive
whenwith noelse out TandNothingfor error-only cases- Compiler-enforced handling of new variants
Next: functional error handling with map and recover.
Learn Kotlin with an AI tutor — free
Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.
- Courses
- 51
- Lessons
- 203
Frequently Asked Questions
Is the “Sealed Result Hierarchies” lesson free?
Yes — any 3 lessons of the Kotlin Academy learning path, including “Sealed Result Hierarchies”, are free to read in full here on the web. After that, CoddyKit PRO unlocks every lesson, plus interactive practice with a built-in code editor and a 24/7 AI tutor. The Kotlin Academy course includes 4 lessons in total.
What will I learn in “Sealed Result Hierarchies”?
Custom result types. You practise Kotlin Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Kotlin Academy?
No prior experience is required. Kotlin Academy on CoddyKit is structured for beginners through advanced learners, so you can start here or from the beginning and move at your own pace. This is lesson 3 of 4.
How long does the “Sealed Result Hierarchies” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Kotlin Academy lesson?
Yes. Every Kotlin Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- The Result Type
- runCatching
- Sealed Result Hierarchies
- Functional Error Handling