Type inference

You already know how to perform type conversion. There are more advanced aspects of it: for example, you know that we cannot assign a variable of Int type to a Long variable. But what happens if we calculate the sum of Int and Long variables? In this case, the type is inferred from the context.

Type inference

What happens when the type is inferred is that the compiler automatically sets the result type to the widest type in the expression. The picture below illustrates the direction of this casting:


Since the type of the result is wider than the previous type, there is no loss of information.


The theory looks pretty clear, so let's take a look at some examples of type inference.

  • from Int to Long:
val num: Int = 100
val longNum: Long = 1000
val result = num + longNum // 1100, Long

Although result is just 1100, it is the sum of Long and Int variables, so the type is automatically cast to Long. If you try to declare a result as Int, you get an error because you cannot assign the value of Long type to an Int variable. You can assign only an Int value or an integer number to a variable of Int type.

  • from Long to Double:
val bigNum: Long = 100000
val doubleNum: Double = 0.0
val bigFraction = bigNum - doubleNum // 100000.0, Double

Short and Byte types

You can see how the result of an expression with variables of different types is automatically cast to the widest type. However, the Byte and Short types are unusual in this respect. If you need to do some calculations with these types, the result of the calculation is Int:

  • Byte and Byte
val one: Byte = 1
val two: Byte = 2
val three = one + two // 3, Int
  • Short and Short
val fourteen: Short = 14
val ten: Short = 10
val four = fourteen - ten // 4, Int
  • Short and Byte
val hundred: Short = 100
val five: Byte = 5
val zero = hundred % five // 0, Int

So what should we do if we want to sum two Byte variables and get a Byte result? Well, in this case, you must manually perform type conversion:

val one: Byte = 1
val five: Byte = 5
val six = (one + five).toByte() // 6, Byte


To sum up, if you have an expression with different numeric types, use these rules to know the type of the result:

  1. If either operand is of type Double, the result is Double.
  2. Otherwise, if either operand is of type Float, the result is Float
  3. Otherwise, if either operand is of type Long, the result is Long.
  4. Otherwise, the result is Int.


The compiler automatically deduces the type of an expression. It helps you omit type conversion in simple cases, but you need to understand how it works to prevent confusion and errors.