Jani
Jani

Reputation: 406

Comparing two types in Dart

I'm looking for a way to compare two types in Dart, and get True when they are the same.

I have a method:

SomeItemType exampleMethod<SomeItemType>(Map<String, dynamic> value) {
    if (SomeItemType.toString() == 'BuiltMap<String, String>') {
      return BuiltMap<String, String>.from(value) as SomeItemType;
    }
    // (...)
}

in which I must check if the type-parameter SomeItemType is actually equal to the type BuiltMap<String, String> or not. The only way I found so far is the above string comparions, which is not too elegant in my opinion.

I have tried to following solutions, but they did not work out for me:

SomeItemType is BuiltMap<String, String>
// returns False

SomeItemType == BuiltMap<String, String>
// error: The operator '<' isn't defined for the type 'Type'.

BuiltMap<String, String> is SomeItemType
// error: The operator '<' isn't defined for the type 'Type'.

Upvotes: 2

Views: 2525

Answers (2)

Sunil Gupta
Sunil Gupta

Reputation: 832

I needed to check if a variable pointed to a function. This worked for me variable is function - the word is

Upvotes: 0

lrn
lrn

Reputation: 71883

You need to detect whether a type variable holds a type which is "the same" as some known type.

I'd probably not go for equality in that check, I'd just check if the type of the variable is a subtype of the known type.

You can do that like:

class _TypeHelper<T> {}
bool isSubtypeOf<S, T>() => _TypeHelper<S>() is _TypeHelper<T>;
// or just ...           => <S>[] is List<T>;
...
  if (isSubtypeOf<T, BuiltMap<String, String>>()) { ... }

If you want to check type equality, then you have to decide what type equality means. The simplest is "mutual subtyping", which would mean:

bool isMutualSubtypes<S, T>() => isSubtypeOf<S, T>() && isSubtypeOf<T, S>();
// or                         => isSubtypeOf<S Function(S), T Function(T)>();
// or                         => isSubtypeOf<void Function<X extends T>() Function(),
//                                           void Function<X extends S>() Function()>();

This will accept, e.g., isMutualSubtypes<void, dynamic>() because both types are top types.

Type identity is much harder to check because the language itself doesn't have that notion. If types are mutual subtypes, they are considered equivalent at run-time (we distinguish void and dynamic statically, but not at run-time). You can try something like:

bool isSameType<S, T>() => S == T;

but equality of Type objects is very underspecified, and not guaranteed to work any better than mutual subtyping. Definitely don't use string comparison:

// Don't use!
bool isSameType<S, T>() => "$S" == "$T"; // BAD!

because it's possible to have different types with the same name.

Upvotes: 4

Related Questions