flutterdartdata-modelingfreezedflutter-freezed

Best way to have a const factory for empty instance in Flutter's freezed


I am trying to figure out the best way to implement a constant factory for "empty" instance of the defined model while keeping its original constructor strict (require all arguments without defaults).

The closest solution I could get is using Union types and Sealed classes with an identical set of parameters.

const factory Costs({
  required bool valid,
  required String names,
  required String prices,
  required String subtotal,
  required String deposit,
  required String deliveryCosts,
  required String total,
  String? errCode,
}) = LoadedCosts;

const factory Costs.empty({
  @Default(false) bool valid,
  @Default('') String names,
  @Default('') String prices,
  @Default('') String subtotal,
  @Default('') String deposit,
  @Default('') String deliveryCosts,
  @Default('') String total,
  String? errCode,
}) = EmptyCosts;

So, this will keep my main factory strict, while allowing getting an empty instance via the second one. Important to notice, I also don't have to match sealed classes within the business logic code (all params are identical in both classes, so I can just access fields directly).

The are 2 points of concern:

Ideally, I would expect it to look something like this:

  const Costs.empty()
  : valid = false,
    names = '',
    prices = '',
    subtotal = '',
    deposit = '',
    deliveryCosts = '',
    total = '',
    errCode = null;

This actually works if you are not using freezed. With freezed, however, I need to redirect the constructor, which starts all the problems.

Any thoughts?


Solution

  • you could actually do this.

    @freezed
    class Costs with _$Costs {
      const factory Costs({
        required bool valid,
        required String names,
        required String prices,
        required String subtotal,
        required String deposit,
        required String deliveryCosts,
        required String total,
        String? errCode,
      }) = LoadedCosts;
    
      factory Costs.empty() => const LoadedCosts(
            deliveryCosts: '',
            deposit: '',
            names: '',
            prices: '',
            subtotal: '',
            total: '',
            valid: false,
          );
    }
    

    Or else, if you want to pass the instance as a default value in a constructor, you could have a static const variable. Since it is const and immutable we cannot change the state of this static instance. Also anyway if we want to change the state in immutable freezed object, we use .copyWith() which obviously provides new instance without changing existing instance state. So i think this could help.

    @freezed
    class Costs with _$Costs {
      const factory Costs({
        required bool valid,
        required String names,
        required String prices,
        required String subtotal,
        required String deposit,
        required String deliveryCosts,
        required String total,
        String? errCode,
      }) = LoadedCosts;
    
      static const emptyCosts = LoadedCosts(
        deliveryCosts: '',
        deposit: '',
        names: '',
        prices: '',
        subtotal: '',
        total: '',
        valid: false,
      );
    }
    

    Hope it helps! Happy coding:)