I am modelling a Dart class with the new null safety types in mind. I believe there are two effective ways to initialize non-nullable properties, calculated from a parameter.

For this example, we will use the Favourite class.

This class uses the initializer list in the constructor.

class Favourite {
  int favouriteId;

  Favourite({required this.favouriteId});

  Favourite.mapFromJson(dynamic json)
      : this.favouriteId = json["favouriteId"];
}

This class uses the 'late' keyword.

class Favourite {
  late int favouriteId;

  Favourite({required this.favouriteId});

  Favourite.mapFromJson(dynamic json) {
    this.favouriteId = json["favouriteId"];
  }
}

When would you use one over the other? Using 'late' feels risky. If I added another named constructor, the compiler would not complain about 'favouriteId' not being initialized.

Are there other options?

Thank you!


Solution 1: Abion47

Neither.

Use a default constructor that initializes the fields themselves and a factory constructor that handles deserializing the json object:

class Favourite {
  final int favouriteId;

  Favourite({required this.favouriteId});

  factory Favourite.fromMap(Map<String, dynamic> map) {
    final favouriteId = json['favouriteId'];
    assert(favouriteId != null && favouriteId is int);

    return Favourite(
      favouriteId: favouriteId,
    );
  }
}

The late keyword can be a source of headache if you don't handle it properly, so in general don't use it unless you have to.


Solution 2: rmtmckenzie

If you're sure the json will always have a "favouriteId", you can write it like this:

class Favourite {
  int favouriteId;

  Favourite({required this.favouriteId});

  Favourite.mapFromJson(Map<String, dynamic?> json):
    assert(() {
      final favouriteId = json["favouriteId"];
      return favouriteId != null && favouriteId is int;
    }()),
    favouriteId = json["favouriteId"] as int;
}

void main() {

  dynamic m = {"favouriteId":2};
  final favourite = Favourite.mapFromJson(m);
  print("favourite id: ${favourite.favouriteId}");

}