Sdk: Generic Type Inheritance Checking

Created on 11 Sep 2020  路  3Comments  路  Source: dart-lang/sdk

Problem

It seems generic type inheritance checking is not easy in Dart.
Solution one will have a long checking code when subtypes amount increased.
Solution two had more creation cost at the runtime.

Is it possible to provide a handy way of checking generic type inheritance?
Such as new keyword(maybe?):

T inherits Parent

Functions and Type Inheritance

void main() {
  checkType<Child>();
}

class Parent {}

class Child extends Parent {}

void checkType<T extends Parent>() {
   ...
}

[==] check

  print('[==] check can only check the exact type: ');
  if (T == Parent) {
    print('Tpye == Parent');
  } else {
    print('Tpye != Parent');
  }

  if (T == Child) {
    print('Tpye == Child');
  } else {
    print('Tpye != Child');
  }

[is] check

  print('\n[is] check fail any tpye check: ');
  if (T is Parent) {
    print('Type is Parent');
  } else {
    print('Type is not Parent');
  }

  if (T is Child) {
    print('Type is Child');
  } else {
    print('Type is not Child');
  }

[switch] check

  print('\n[switch] can only check the exact type: ');
  switch (T) {
    case Parent:
      print('Type match case Parent');
      break;
    default:
      print('Type is not matched case Parent');
  }

  switch (T) {
    case Child:
      print('Type match case Child');
      break;
    default:
      print('Type is not matched case Child');
  }

Solution one

  if (T == Parent || T == Child) {
    print('Type is either Parent or Child');
  } else {
    print('Type is neither Parent nor Child');
  }

Solution two

  if (<T>[] is List<Parent>) {
    print('Type is either Parent or Child');
  } else {
    print('Type is neither Parent nor Child');
  }

Results

[==] check can only check the exact type: 
Tpye != Parent
Tpye == Child

[is] check fails any type check: 
Type is not Parent
Type is not Child

[switch] can only check the exact type: 
Type is not matching case Parent
Type match case Child

solution one: 
Type is either Parent or Child

solution two: 
Type is either Parent or Child
type-question

Most helpful comment

If you have a type variable <T extends Parent> and want to check whether the type bound to T is a subtype of Child, then you can't do it directly. There are not affordances for comparing type variables directly to other types, only for checking instances against the type.

There is a simple workaround, though, using a helper class or function.

The simplest approach is:

bool isSubtype<S, T>() => <S>[] is List<T>;

Then you can ask isSubtype<T, Child>() and get a true when T represents a subtype of Child, and a false when T is Parent.

A more generalized helper class could be:

class TypeHelper<T> {
  const TypeHelper();
  bool operator >=(TypeHelper other) => other is TypeHelper<T>;
  bool operator <=(TypeHelper other) => other >= this;
  bool operator >(TypeHelper other) => this >= other && !(other >= this);
  bool operator <(TypeHelper other) => other >= this && ! (this >= other);
}

Then you could do:

var tType = TypeHelper<T>();
if (tType <= const TypeHelper<Child>()) ... 

(In general, don't use Type objects for anything, they're not good solutions to anything except using dart:mirrors).

All 3 comments

If you have a type variable <T extends Parent> and want to check whether the type bound to T is a subtype of Child, then you can't do it directly. There are not affordances for comparing type variables directly to other types, only for checking instances against the type.

There is a simple workaround, though, using a helper class or function.

The simplest approach is:

bool isSubtype<S, T>() => <S>[] is List<T>;

Then you can ask isSubtype<T, Child>() and get a true when T represents a subtype of Child, and a false when T is Parent.

A more generalized helper class could be:

class TypeHelper<T> {
  const TypeHelper();
  bool operator >=(TypeHelper other) => other is TypeHelper<T>;
  bool operator <=(TypeHelper other) => other >= this;
  bool operator >(TypeHelper other) => this >= other && !(other >= this);
  bool operator <(TypeHelper other) => other >= this && ! (this >= other);
}

Then you could do:

var tType = TypeHelper<T>();
if (tType <= const TypeHelper<Child>()) ... 

(In general, don't use Type objects for anything, they're not good solutions to anything except using dart:mirrors).

I'll take the emojis as a sign we've answered the question. 馃帀

Yes! Many thx!@lrhn

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jmesserly picture jmesserly  路  3Comments

DartBot picture DartBot  路  3Comments

ranquild picture ranquild  路  3Comments

matanlurey picture matanlurey  路  3Comments

rinick picture rinick  路  3Comments