Home > Back-end >  How to create generic class of type T, where T is Type variable?
How to create generic class of type T, where T is Type variable?

Time:06-22

I'm trying to create list of generic typed class from mixed-type list.

It works, but the problem is each Data instance type is dynamic.

class Data<T> {
   final T value;

   const Data(this.value);
}

final List<dynamic> bases = [...];

final List<Data> data = bases.map((b) {
    return Data(b);
}).toList();

Attempt #2

class Data<T> {
   final T value;

   const Data(this.value);
}

final List<dynamic> bases = [...];

final List<Data> data = bases.map((b) {
    final Type T = b.runtimeType;
    return Data<T>(b);
}).toList(); // List<Data<dynamic>>

But it fails, due to: The name 'T' isn't a type so it can't be used as a type argument. Try correcting the name to an existing type, or defining a type named

CodePudding user response:

Generic type parameters must be known statically (i.e., at compile-time). If you start off with a heterogeneous List<dynamic>, then the static type of each element is dynamic, and therefore when you construct a Data object from that element, it will be Data<dynamic>.

If your heterogeneous list has a limited number of types, you could do:

var data = <Data<dynamic>>[];
for (var b in bases) {
  if (b is Foo) {
    var d = Data(b); // `d` is of type `Data<Foo>`
    data.add(d);
  } else if (b is Bar) {
    var d = Data(b); // `d` is of type `Data<Bar>`
    data.add(d);
  } else {
    throw UnimplementedError('Unrecognized type: ${b.runtimeType}');
  }
}

(Note that if you do data.add(Data(b)) in the above, the Data object will be constructed as Data<dynamic> because the generic type parameter will be inferred from data (of type List<Data<dynamic>>) instead of from b.)

Otherwise what you want isn't really possible.

  • Related