Why dart infers the variable type as a int when I explicitly say the type is double?

Viewed 148

Here is the example from the doc

The doc says the Integer literals are automatically converted to doubles when necessary:

double z = 1; // Equivalent to double z = 1.0.

But when I check the runtimeType the type is int

print(z.runtimeType); // prints to int
1 Answers

I guess you are testing using dartpad.dev or compiled your code to JavaScript. In JavaScript, there are no separate types of int and double so Dart are just guessing the type, when using runtimeType, based on the current value since JavaScript are representing all numbers as double internally.

But if we are running in the Dart VM or compiled to native code, we can determine the type. So you example will return double as the type of z if running with Dart VM.

void main(List<String> args) {
  print(1.1.runtimeType); // dartpad: double, dartvm: double
  print(1.0.runtimeType); // dartpad: int, dartvm: double
  print(1.runtimeType);   // dartpad: int, dartvm: int
}

See also the note about the different behavior of the int type, when compiled to JavaScript, in the Dart documentation: https://api.dart.dev/stable/2.12.3/dart-core/int-class.html

A more detailed example is showed here where we can see how a double declared variable behave differently when running the Dart code in DartVM vs as compiled JavaScript:

void main(List<String> args) {
  print('| toString | runtimeType | is int | is double |');

  for (double i = 0; i <= 2; i += 0.5) {
    print('| ${i.toString().padRight(8)} | '
        '${i.runtimeType.toString().padLeft(11)} | '
        '${(i is int).toString().padLeft(6)} | '
        '${(i is double).toString().padLeft(9)} |');
  }
}

Which returns the following using DartPad:

| toString | runtimeType | is int | is double |
| 0        |         int |   true |      true |
| 0.5      |      double |  false |      true |
| 1        |         int |   true |      true |
| 1.5      |      double |  false |      true |
| 2        |         int |   true |      true |

While DartVM returns:

| toString | runtimeType | is int | is double |
| 0.0      |      double |  false |      true |
| 0.5      |      double |  false |      true |
| 1.0      |      double |  false |      true |
| 1.5      |      double |  false |      true |
| 2.0      |      double |  false |      true |

And for int we can do the same:

void main(List<String> args) {
  print('| toString | runtimeType | is int | is double |');

  for (int i = 0; i <= 2; i += 1) {
    print('| ${i.toString().padRight(8)} | '
        '${i.runtimeType.toString().padLeft(11)} | '
        '${(i is int).toString().padLeft(6)} | '
        '${(i is double).toString().padLeft(9)} |');
  }
}

DartPad:

| toString | runtimeType | is int | is double |
| 0        |         int |   true |      true |
| 1        |         int |   true |      true |
| 2        |         int |   true |      true |

DartVM:

| toString | runtimeType | is int | is double |
| 0        |         int |   true |     false |
| 1        |         int |   true |     false |
| 2        |         int |   true |     false |
Related