Kotlin/JS exhaustivity check on enums?

  Kiến thức lập trình

I am investigating into the integration of a Kotlin Multiplatform library into an existing JS project. I am struggling with the exhaustivity check on enums and sealed classes on the JS side.

In JS, an enum is usually a union of values, which gives exhaustivity check safety with type checkers (TypeScript or Flow):

type MyEnum = 'RED' | 'BLUE';

function getText(e: MyEnum): string{
    switch(e){
        case 'RED': return 'red';
        case 'BLUE': return 'blue';
    }
}

If later on, someone adds a new value to MyEnum, I’ll get errors from the type checker inside getText. It’s the same in Kotlin:

@JsExport
enum class MyEnum {
    RED, BLUE
}

fun getText(e: MyEnum): String{
    return when(e){ // I'll get an exhaustivity error here if a new enum member is added
        MyEnum.RED -> "red"
        MyEnum.BLUE -> "blue"
    }
}

The problem though is that Kotlin/JS will generate an abstract class for MyEnum, which loses the information that there can be only two values.

This means that this is how I would have to handle it on the JS side:

// MyEnum is generated from the Kotlin code above
function getText(e: MyEnum): string{
    switch(e){
        case MyEnum.RED: return 'red';
        case MyEnum.BLUE: return 'blue';
        default: throw Error('This should never happen!')
    }
}

Not only to get rid of errors I need to add a default branch, but this means that I lose any type safety given by exhaustivity checks! If someone later on add a new enum members, then instead of failing at “compile time”, it would fail at runtime!

This makes it a bad candidate for a library at it means updates in the library could break clients at runtime.
Sealed classes also suffer from the same problem.

Is there any workaround to keep the same type safety as if the library was written in plain JS?

Theme wordpress giá rẻ Theme wordpress giá rẻ Thiết kế website

LEAVE A COMMENT