GusHill
GusHill

Reputation: 65

Restrictions on Type in dart

So, basically I need to create restrictions of which types can be used in a Type variable, something like this:

class ElementFilter<T extends Element> {
    final Type<T> elementType; // What I want is something like Type<T>, but Type does not have a generic parameter
    ElementFilter(this.elementType);
}

List<T> filterElements<T extends Element>(ElementFilter<T> element) {
    return elements.where((el) => _isOfType(el, element.type)).toList();
}

filterElements(ElementFilter(ClassThatExtendsElement)); // Would work fine
filterELements(ElementFilter(String)); // Error, String does not extends Element

So it would only be possible to create ElementFilters with types that extend Element. Is this possible in some way?

Upvotes: 0

Views: 246

Answers (2)

lrn
lrn

Reputation: 71623

I highly recommend not using Type objects at all. Ever. They're pretty useless, and if you have the type available as a type parameter, you're always better off. (The type variable can always be converted to a Type object, but it can also be actually useful in many other ways).

Example:

class ElementFilter<T extends Element> {
  bool test(Object? element) => element is T;
  Iterable<T> filterElements(Iterable<Object?> elements) => 
      elements.whereType<T>();
}

List<T> filterElements<T extends Element>(ElementFilter<T> filter) =>
    filter.filterElements(elements).toList();

filterElements(ElementFilter<ClassThatExtendsElement>()); // Would work fine
filterElements(ElementFilter<String>()); // Error, String does not extends Element

Upvotes: 1

jamesdlin
jamesdlin

Reputation: 89946

I think you probably want:

/// Example usage: ElementFilter<ClassThatExtendsElement>();
class ElementFilter<T extends Element> {
  final Type elementType;
  ElementFilter() : elementType = T;
}

Unfortunately, there's no way to make the generic type argument non-optional. You will have to choose between having a required argument and having a compile-time constraint on the Type argument.

Dart doesn't support algebraic types, so if you additionally want to support a finite set of types that don't derive from Element, you could make specialized derived classes and require that clients use those instead of ElementFilter. For example:

class StringElementFilter extends ElementFilter<Element> {
  @override
  final Type elementType = String;
}

(You also could create a StringElement class that extends Element if you want, but at least for this example, it would serve no purpose.)

Upvotes: 1

Related Questions