135

Dart specification states:

Reified type information reflects the types of objects at runtime and may always be queried by dynamic typechecking constructs (the analogs of instanceOf, casts, typecase etc. in other languages).

Sounds great, but there is no instanceof-like operator. So how do we perform runtime type-checking in Dart? Is it possible at all?

Günter Zöchbauer
  • 490,478
  • 163
  • 1,733
  • 1,404
Idolon
  • 26,581
  • 12
  • 93
  • 121

8 Answers8

197

The instanceof-operator is called is in Dart. The spec isn't exactly friendly to a casual reader, so the best description right now seems to be http://www.dartlang.org/articles/optional-types/.

Here's an example:

class Foo { }

main() {
  var foo = new Foo();
  if (foo is Foo) {
    print("it's a foo!");
  }
}
Günter Zöchbauer
  • 490,478
  • 163
  • 1,733
  • 1,404
Patrick
  • 2,740
  • 1
  • 13
  • 11
  • 1
    Looks like there is no mention of `is` operator at all in the specification. It's better to refere to the grammar file in Dart sources: https://code.google.com/p/dart/source/browse/trunk/dart/language/grammar/Dart.g – Idolon Oct 10 '11 at 17:11
  • 4
    @Idolon, the `is` operator is defined on page 59 of the spec, section 10.30 'Type test' – Duncan Oct 11 '11 at 08:53
  • 8
    `is` and `is!` can be found in the [Operators](https://dart.dev/guides/language/language-tour#type-test-operators) section of the Dart language tour. – SoftWyer Jun 25 '19 at 16:02
  • 2
    new syntax is `getTypeName(dynamic obj) => obj.runtimeType;` – Mahdi Imani Sep 28 '19 at 07:53
  • 3
    `!=` but `is!`...confuses me not it does – atreeon Oct 25 '19 at 18:45
  • Is there a way to use the runtimeType to check whether a particular named constructor was used? – TryHard May 02 '20 at 14:08
  • 1
    The Dart Language Tour has sections on equality operators: https://dart.dev/guides/language/language-tour#equality-and-relational-operators and type operators: https://dart.dev/guides/language/language-tour#type-test-operators – Yudhishthir Singh May 02 '20 at 18:26
50

Dart Object type has a runtimeType instance member (source is from dart-sdk v1.14, don't know if it was available earlier)

class Object {
  //...
  external Type get runtimeType;
}

Usage:

Object o = 'foo';
assert(o.runtimeType == String);
sbedulin
  • 3,413
  • 21
  • 30
  • 14
    RuntimeType is only for debugging purposes and the application code shouldn't depend on it. It can be overridden by classes to return fake values and probably returns unusable values when transpiled to JS – Günter Zöchbauer Mar 11 '16 at 21:33
  • 1
    Thanks for your remark, I'm pretty new to Dart, and I agree that `runtimeType` may be overriden by classes, although I can't think of a reason why they would. (external code can't set the value sinse it's a getter) Personally, I would stick to `is` and reflection. – sbedulin Mar 11 '16 at 22:47
  • 2
    It's fine this is mentioned here. It's not very obvious that `runtimeType` has these limitations. – Günter Zöchbauer Mar 12 '16 at 08:43
  • Gunter, is it still the case that `runtimeType` should only be used for debugging purposes? I ask because there isn't any mention of this in the docs for Object, or elsewhere (that I could find). – Matt C Apr 11 '19 at 20:22
  • @MattC yes, I was using `runtimeType` to generate HTML classes on the fly, it works with development build, but fails with release build, e.g. in my case result is `minified:ed` instead of `column` – Spyryto Apr 19 '19 at 16:59
  • 3
    @GünterZöchbauer comment is no longer true in Dart 2. It should be fine to use it now. – vovahost Nov 13 '19 at 14:33
  • @vovahost I'm mot aware of any related changes. Why do you think my comment is obdolete? – Günter Zöchbauer Nov 13 '19 at 15:55
  • @GünterZöchbauer I'm not expert on Dart 2 differences. I commented based on this discussion https://ibb.co/WcVJzhz https://ibb.co/zmgq168 Let me know what you think. – vovahost Nov 13 '19 at 17:23
  • I'm not sure why he thinks it's ok in Dart 2. Perhaps I missed something. – Günter Zöchbauer Nov 13 '19 at 17:46
27

object.runtimeType returns the type of object

For example:

print("HELLO".runtimeType); //prints String
var x=0.0;
print(x.runtimeType); //prints double
Raj Yadav
  • 5,396
  • 2
  • 29
  • 24
  • 12
    The answer from sbedulin already explains that. There is no point in adding the same answer as existing ones. See also the comments below his answer. – Günter Zöchbauer Jan 24 '19 at 11:53
18

As others have mentioned, Dart's is operator is the equivalent of Javascript's instanceof operator. However, I haven't found a direct analogue of the typeof operator in Dart.

Thankfully the dart:mirrors reflection API has recently been added to the SDK, and is now available for download in the latest Editor+SDK package. Here's a short demo:

import 'dart:mirrors'; 

getTypeName(dynamic obj) {
  return reflect(obj).type.reflectedType.toString();
}

void main() {
  var val = "\"Dart is dynamically typed (with optional type annotations.)\"";
  if (val is String) {
    print("The value is a String, but I needed "
        "to check with an explicit condition.");
  }
  var typeName = getTypeName(val);
  print("\nThe mirrored type of the value is $typeName.");
}
Rob
  • 5,013
  • 5
  • 37
  • 60
  • [Is Dart a statically typed language?](https://dart.dev/faq#q-is-dart-a-statically-typed-language) – Lii Jun 06 '19 at 17:58
  • it is good solution but, we have error: ``Unsupported operation: dart:mirrors is no longer supported for web apps`` – Mahdi Imani Sep 28 '19 at 07:50
  • @Lii This answer was written for Ecma TC52. See https://dart.dev/faq – Rob Oct 25 '19 at 21:53
  • Be aware that Flutter, if you're using that, disables reflection (because it breaks tree shaking). – Ian Apr 14 '21 at 18:26
13

There are two operators for type testing: E is T tests for E an instance of type T while E is! T tests for E not an instance of type T.

Note that E is Object is always true, and null is T is always false unless T===Object.

Duncan
  • 79,697
  • 10
  • 108
  • 148
  • Could you explain what is meant by by `T===Object`? Dart doesn't have the triple equals operator, but you chose to use it rather than double equals, so I assume the difference has significance. – Matt C Apr 10 '19 at 17:02
  • @MattC That was written more than 7 years ago! I think what I meant was `null is Object` would be true but `null is T` false for any other type T. tbh though I haven't been near Dart for many years now so can't be certain. – Duncan Apr 12 '19 at 14:23
7

Just to clarify a bit the difference between is and runtimeType. As someone said already (and this was tested with Dart V2+) the following code:

class Foo { 
  Type get runtimeType => String;
}
main() {
  var foo = new Foo();
  if (foo is Foo) {
    print("it's a foo!");
  }
  print("type is ${foo.runtimeType}");

}

will output:

it's a foo! 
type is String

Which is wrong. Now, I can't see the reason why one should do such a thing...

Edoardo
  • 2,603
  • 1
  • 20
  • 28
6

Simply call

print(unknownDataType.runtimeType)

on the data.

Alish Giri
  • 586
  • 6
  • 12
5

Exact type matching is done via runtimeType property, checking if the instance or any parent (in inheritance chain) is of the given type is done with is operator:

class xxx {}

class yyy extends xxx {}

void main() {
  var y = yyy();
  
  print(y is xxx);
  print(y.runtimeType == xxx);
}

Returns:

true
false
Maxim Saplin
  • 1,353
  • 19
  • 13