# Is a sealed interface the best way to handle union types

**URL:** https://discuss.kotlinlang.org/t/is-a-sealed-interface-the-best-way-to-handle-union-types/28495
**Category:** Support
**Created:** [April 21, 2024, 11:38pm UTC](https://discuss.kotlinlang.org/t/is-a-sealed-interface-the-best-way-to-handle-union-types/28495 "2024-04-21T23:38:00Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![mobeigi](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/mobeigi/32/10845_2.png) [@mobeigi](https://discuss.kotlinlang.org/u/mobeigi)
#### Post date: [April 21, 2024, 11:38pm UTC](https://discuss.kotlinlang.org/t/is-a-sealed-interface-the-best-way-to-handle-union-types/28495/1 "2024-04-21T23:38:00Z")

</div>

Hiya!

This is my current problem. I have a third party API which returns data for me. Now the API can return 2 completely different response bodies based on if request was successful or not. So my function has a union return type. In my example, lets call the return types `A` and `B`. In my case even though I have created classes `A` and `B` myself it does not make sense for them to know about how they are used. I want to avoid making `A` or `B` implement 10-20 different classes.

From what I see there are some possible solutions:

- Class composition with nullable types (doesn’t guarantee you don’t have all nulls so can lead to NPE)
- Generic class that stores generic object (doesn’t provide exhaustion when handling cases due to `Any` type)
- Sealed interfaces / classes

I went with the sealed interface approach and want to confirm that this is currently the best Kotlin JVM solution available in the absence of language supported union types.

**Service.kt:**

```auto
fun myApiQuery(): QueryResponse {
  ...  
  if (apiCallWasSuccessful) {
       return QueryResponse.AWrapper(obj) // obj here is serialised success response of type `A` from API
  }
  else {
       return QueryResponse.BWrapper(obj) // obj here is serialised error response of type `B` from API
  }
}

```

**QueryResponse.kt:**

```auto
sealed interface QueryResponse {

    data class AWrapper(
        val response: A
    ) : QueryResponse 

    data class BWrapper(
        val response: B,
    ) : QueryResponse 
}

```

**ConsumerUsageExample.kt:**

```auto
fun main() {
  val myApiQueryResponse = Service.myApiQuery()
  check(myApiQueryResponse.response is AWrapper)
  val a: A = myApiQueryResponse.response
  // Continue using A as required
  // Alternatively, could use same logic to use B
  // or a when clause to handle multiple cases
}

```

---

<div class="post-metadata">

### Author: ![urosjarc](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/urosjarc/32/10798_2.png) [@urosjarc](https://discuss.kotlinlang.org/u/urosjarc)
#### Post date: [April 22, 2024, 4:38am UTC](https://discuss.kotlinlang.org/t/is-a-sealed-interface-the-best-way-to-handle-union-types/28495/2 "2024-04-22T04:38:01Z")

</div>

If external API returns many variation of the request then I would advise to get  
response in the form JsonElement like so… You can then check internal structure of JsonElement  
and transform JsonElement into a apropriate class object…

In my case I joust use the raw JsonElement because why bother?

```kotlin
val res = client.get("https://something.com/data")
val body: JsonElement = res.body<JsonElement>()

```

and also to create helper functions on Json primitives to ease the development…

```kotlin
public fun JsonElement.obj(key: String): JsonObject = (this as JsonObject).get(key = key)!! as JsonObject

public fun JsonElement.array(key: String): JsonArray = (this as JsonObject).get(key = key)!! as JsonArray

public fun JsonElement.ele(key: String): JsonPrimitive = (this as JsonObject).get(key = key)!! as JsonPrimitive

```

```kotlin
	body.obj(key = "forecast1h")
					.array(key = "features").first()
					.obj("properties")
					.array("days").flatMap { day ->
						day.array("timeline").map { time ->
							WeatherInfo(
								instant = Instant.parse(time.ele("valid").content),
								temperature = time.ele("t").int,
								clouds =
									WeatherInfo.Clouds(
										condition = WeatherInfo.Clouds.Condition.entries.first { it.value == time.ele("wwsyn_decodeText").content },
										icon = time.ele("clouds_icon_wwsyn_icon").content,
										description = time.ele("clouds_shortText").content,
										height = time.ele("cloudBase_shortText").content,
									),
								wind =
									WeatherInfo.Wind(
										description = time.ele("ff_shortText").content,
										direction = time.ele("dd_shortText").content,
										speed = time.ele("ff_val").int,
									),
								humidity =
									WeatherInfo.Humidity(
										description = time.ele("rh_shortText").content,
										percentage = time.ele("rh").int,
									),
								pressure =
									WeatherInfo.Presure(
										description = time.ele("pa_shortText").content,
										value = time.ele("msl").int,
									),
							)
						}
					}

```

---

<div class="post-metadata">

### Author: ![Skater901](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/skater901/32/10163_2.png) [@Skater901](https://discuss.kotlinlang.org/u/Skater901)
#### Post date: [April 25, 2024, 11:21am UTC](https://discuss.kotlinlang.org/t/is-a-sealed-interface-the-best-way-to-handle-union-types/28495/3 "2024-04-25T11:21:46Z")

</div>

Yeah I think it’s the best option. Tbh, it sounds like you’re basically describing a Monad. I’ve actually come across the Arrow library before, which seems to do what you would want it to do: [Either & Ior | Arrow](https://arrow-kt.io/learn/typed-errors/either-and-ior/)
