# Why type can't be inferred for base class or interface? Kotlin 1.4

**URL:** <https://discuss.kotlinlang.org/t/why-type-cant-be-inferred-for-base-class-or-interface-kotlin-1-4/20758>\
**Category:** Language Design\
**Created:** [February 4, 2021, 4:54pm UTC](https://discuss.kotlinlang.org/t/why-type-cant-be-inferred-for-base-class-or-interface-kotlin-1-4/20758 "2021-02-04T16:54:36Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![docanod](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/docanod/32/5001_2.png) [@docanod](https://discuss.kotlinlang.org/u/docanod)\
**Post date:** [February 4, 2021, 4:54pm UTC](https://discuss.kotlinlang.org/t/why-type-cant-be-inferred-for-base-class-or-interface-kotlin-1-4/20758/1 "2021-02-04T16:54:36Z")

</div>

```
fun main() {
    val typeB = convert(C())
}

fun convert(type: A): B? {
    return if (type is C || type is D) {
        type // ->
    } else {
        null
    }
}

interface A
open class B: A // can be interface
class C: B()
class D: B()

```

Why am I getting this error: Type mismatch: inferred type is A but B? was expected  
Or try it here: [Kotlin Playground: Edit, Run, Share Kotlin Code Online](https://pl.kotl.in/d5eVBKkDU)

---

<div class="post-metadata">

**Author:** ![wdoker](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/wdoker/32/4748_2.png) [@wdoker](https://discuss.kotlinlang.org/u/wdoker)\
**Post date:** [February 4, 2021, 5:25pm UTC](https://discuss.kotlinlang.org/t/why-type-cant-be-inferred-for-base-class-or-interface-kotlin-1-4/20758/2 "2021-02-04T17:25:36Z")

</div>

Looks like a simplest reproducer. Do you have any real-world use cases? I can’t imagine one and I’m not surprised it’s not handled by Kotlin type inference.

If you expect to see type “B” in a branch, why not write an explicit check for type “B”? Besides being more explicit, it is also more readable and won’t cause any type inference problems.

---

<div class="post-metadata">

**Author:** ![wdoker](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/wdoker/32/4748_2.png) [@wdoker](https://discuss.kotlinlang.org/u/wdoker)\
**Post date:** [February 4, 2021, 5:36pm UTC](https://discuss.kotlinlang.org/t/why-type-cant-be-inferred-for-base-class-or-interface-kotlin-1-4/20758/3 "2021-02-04T17:36:22Z")

</div>

Also note, Kotlin cannot make any guarantees on the class hierarchy unless base classes explicitly marked as `sealed`.

---

<div class="post-metadata">

**Author:** ![akurczak](https://avatars.discourse-cdn.com/v4/letter/a/f07891/32.png) [@akurczak](https://discuss.kotlinlang.org/u/akurczak)\
**Post date:** [February 4, 2021, 5:53pm UTC](https://discuss.kotlinlang.org/t/why-type-cant-be-inferred-for-base-class-or-interface-kotlin-1-4/20758/4 "2021-02-04T17:53:17Z")

</div>

It seems Kotlin compiler does not support smart casts for conditions combined with or.  
It works when you have a single condition or when conditions are and-combined:

```run-kotlin
fun main() {
    println(convert(C()))
}

fun convert(type: Any): B? {
    if (type is C && type is D) {
        return type
    } else if (type is C && type is Int) {
        return type
    } else if (type is C) {
        return type
    } else if (type is D) {
        return type
    } else {
        return null
    }
}

interface A
open class B: A // can be `interface B: A`
class C: B()
class D: B()

```

This issue was already reported some time ago: [https://youtrack.jetbrains.com/issue/KT-1982](https://youtrack.jetbrains.com/issue/KT-1982)  
However it doesn’t seem to be popular or have a lot of use cases, so I wouldn’t expect this anytime soon.  
Still, if you need it, I’d recommend to upvote the issue and describe your use case in the comment.

---

<div class="post-metadata">

**Author:** ![docanod](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/docanod/32/5001_2.png) [@docanod](https://discuss.kotlinlang.org/u/docanod)\
**Post date:** [February 5, 2021, 8:17am UTC](https://discuss.kotlinlang.org/t/why-type-cant-be-inferred-for-base-class-or-interface-kotlin-1-4/20758/5 "2021-02-05T08:17:07Z")

</div>

Yes it is from real example. Can’t just use type B because there are other cases of B class/interface inheritance:

```
return when (type) {
    is C, is D -> type // doesn't work
    is E -> update(type)
    is F -> type.copy(...)
    else -> null 
}

```

Of course, there is a workaround:

```
return when {
    type is B && (type is C || type is D) -> type // or is C, is D -> type as B
    type is E -> update(type)
    type is F -> type.copy(...)
    else -> null 
}

```

but it doesn’t look concise
