Dart - Getting Runtime Type of Object

This tutorial shows you how to get the runtime type of an object in Dart.

Sometimes you may need to know what is the type of an object at runtime. The process is called runtime type identification. If you use dynamic type and you want to assign the variable to another variable with static type, to avoid Unhandled exception being thrown, it's better to check the variable type first.

For this tutorial, there are three classes: Shape, Circle, and Rectangle. Both Circle and Rectangle extend Shape which means they are the subclasses of Shape.

  class Shape {
    String color;

    Shape({this.color});
  }

  class Circle extends Shape {
    double radius;

    Circle({color, this.radius}) : super(color: color);
  }

  class Rectangle extends Shape {
    double length;
    double width;

    Rectangle({color, this.length, this.width}) : super(color: color);
  }

Using is

is can be used to check whether an object is an instance of a type.

  void main() {
    Circle circle = new Circle(color: 'red', radius: 10);

    print(circle is Circle); // true
    print(circle is Shape); // true
    print(circle is Rectangle); // false
  }

If you run the code, you will get true for the first case as circle object is the instance of Circe indeed. For the second case, you will also get true as circle can also be considered as a Shape because Circle is the subclass of Shape. For the last case, the output is false as the object is not a Rectangle obviously.

We can conclude that is returns true only if the object's type is the same or the subtype of the Type on the right side of is. Therefore, you can use is to check whether an object is assignable to a type.

Using runtimeType

Dart objects have runtimeType property which returns Type. To check whether the object has a certain type, use == operator. Unlike is, it will only return true if compared to an exectly same type, which means comparing it with its super class will return false.

  void main() {
    Circle circle = new Circle(color: 'red', radius: 10);

    Type type = circle.runtimeType;
    print(type == Shape); // false
    print(type == Circle); // true
    print(type == Rectangle); // true
  }

Warning: runtimeType can be overriden

One can create a class that override its runtimeType property, as you can see on the below code. It may cause the property not returning the real type of the object.

  class Circle extends Shape {
    double radius;

    Circle({color, this.radius}) : super(color: color);

    Type get runtimeType {
      return int;
    }
  }

In conclusion, choose to use is or runtimeType based on the case. If you want to get the exact type of an object, use runtimeType property. If you want to check whether an object is assignable to a particular type, use is which also returns true if the object is checked against its super class.