4

What I'm trying to achieve

I am trying to create a generic Dart method that takes a generic type T where T has to implement class IModel. However,

Problem

It seems like I can't set an implements constraint on type T, only an extends. For example <T implements IModel does not work but <T extends IModel> works.

Code

IModel.dart which serves as an interface:

class IModel {
  IModel();

  factory IModel.fromJson(Map<String, dynamic> json) {
    return IModel();
  }

  Map<String, dynamic> toJson() => {};

  IModel clone() {
    return IModel();
  }
}

MyModel.dart, an example that implements IModel:

import 'dart:core';
import 'package:.../helpers/DateTimeHelper.dart';
import 'package:.../helpers/StringHelper.dart';
import 'package:.../models/IModel.dart';

class MyModel implements IModel {
  String id;
  String name;
  String companyId;
  String projectId;
  String description;
  DateTime created;
  DateTime updated;

  MyModel({this.id, this.name, this.description, this.created, this.updated, this.companyId, this.projectId});

  factory MyModel.fromJson(Map<String, dynamic> json) {
    return MyModel(id: json["id"], name: json["name"], created: DateTime.parse(json["created"]), updated: DateTime.parse(json["updated"]), description: json["description"], companyId: json["companyId"], projectId: json["projectId"]);
  }

  Map<String, dynamic> toJson() => {
        "Id": id,
        "Name": name,
        "Description": description,
        "CompanyId": companyId,
        "ProjectId": projectId,
        "Created": created.toIso8601String(),
        "Updated": updated.toIso8601String()
      };

  MyModel clone() {
    return new MyModel(id: StringHelper.clone(id), companyId: StringHelper.clone(companyId), created: DateTimeHelper.clone(created), updated: DateTimeHelper.clone(updated), name: StringHelper.clone(name), projectId: StringHelper.clone(projectId), description: StringHelper.clone(description));
  }
}

ModelHelper.dart with the generic method:

import 'dart:convert';

import 'package:.../models/IModel.dart';

// 'T implements IModel' not working, but 'T extends IModel' does as constraint.
abstract class ModelHelper {
  static List<T> listFromJson<T implements IModel>(String json) {
    List l = jsonDecode(json)["data"];
    var models = l.map((m) => T.fromJson(m)).toList();
    return models;
  }
}

Additional questions/conclusion

Are implements constraints not supported in Dart? Do all T classes simply have to extend IModel?

EggBender
  • 888
  • 15
  • 36

1 Answers1

9

Problem

It seems like I can't set an implements constraint on type T, only an extends. For example <T implements IModel does not work but works.

This is not a problem. You can safely use <T extends IModel>, even for classes that implements IModel:

abstract class Abstract {}

class Concrete implements Abstract {}

void function<T extends Abstract>(T value) {
  print(value);
}

void main() {
  function<Concrete>(Concrete()); // works
}
Rémi Rousselet
  • 256,336
  • 79
  • 519
  • 432