Question: In the following code `"Happy Halloween!"`, `42`, etc. are flagged as "Type mismatch." (Required: T, Found: String (or Int)) but shouldn't the compiler be able to infer that the return value is of the correct type from the type check?

```
interface Type<T>
class StringType() : Type<String>
class IntType1() : Type<Int>
class IntType2(val a: Int, val b: Int) : Type<Int>

fun <T> something(type: Type<T>): T = when (type) {
    is StringType -> "Happy Halloween!"
    is IntType1 -> 42
    is IntType2 -> type.a * type.a + type.b * type.b + type.a * type.b
    else -> throw IllegalArgumentException()
}

```

Answer: 
You could write this:

```
interface Type<T>
class StringType() : Type<String>
class IntType1() : Type<Int>
class IntType2(val a: Int, val b: Int) : Type<Int>

inline fun <reified T> something(type: Type<T>): T {
    val result = when(type) {
        is StringType -> "Happy Halloween"
        is IntType1 -> 42
        is IntType2 -> type.a * type.a + type.b * type.b + type.a * type.b
        else -> throw IllegalArgumentException()
    }
    return if (result is T) result else throw Exception() 
}

```

Running the following:

```
fun main(args: Array<String>) {
    println(something(StringType()))
    println(something(IntType1()))
    println(something(IntType2(2, 3)))
}

```

Will give you this output:

```
Happy Halloween
42
19

```

Learn more about inline functions and reified parameters here: [Reified type parameters](https://kotlinlang.org/docs/reference/inline-functions.html#reified-type-parameters).
When the compiler applies type erasure the return type is going to be defined. So, let's say, you use a String... your method is going to be like:

```
fun something(type: Type<String>): String = when (type) {
    is StringType -> "Happy Halloween!"
    is IntType1 -> 42 //Wrong: you must return String!
    is IntType2 -> type.a * type.a + type.b * type.b + type.a * type.b   
    else -> throw IllegalArgumentException()
}

```

This thing is: **you must know your return type at compile time**. If you dont know this, you have to tell that to the compiler:

```
fun <T> something(type: Type<T>): Any = when (type) {
    is StringType -> "blabla"
    is IntType1 -> 42
    is IntType2 -> type.a * type.a + type.b * type.b + type.a * type.b
    else -> throw IllegalArgumentException()
}

```

Sorry this code it's not what you are hopping, you are going to make a cast after the method is returned...

But you can this:

```
fun <T> something(type: Type<T>): T = when (type) {
        is StringType -> type.b
        //is IntType1 -> 42 remove this!
        is IntType2 -> type.a * type.a + type.b * type.b + type.a * type.b
        else -> throw IllegalArgumentException()
    }

```

assuming the type.a and type.b are parametized as T. Then your code will work just fine.