@freezed copyWith missing с запечатанными классами

В следующем фрагменте функция state.copyWith недоступна.

      @freezed
class MyState with _$MyState {
  @JsonSerializable(fieldRename: FieldRename.snake, explicitToJson: true)
  const factory MyState({@Default(0) int counter,}) = _MyState;
  const factory MyState.initial({@Default(0) int counter}) = Initial;
  const factory MyState.loading() = Loading;
  const factory MyState.one() = One;
  const factory MyState.two() = Two;

  factory MyState.fromJson(Map<String, dynamic> json) =>
      _$MyStateFromJson(json);
}

class MyStateNotifier extends StateNotifier<MyState> {
  MyStateNotifier() : super(MyState.initial());

  Future<void> one() async {
    state = MyState.loading();
    await Future.delayed(Duration(seconds: 5));
    state.copyWith(counter: 1);
  }
}

Однако, когда я удаляю запечатанные классы, функция copyWith становится доступной.

      @freezed
class MyState with _$MyState {
  @JsonSerializable(fieldRename: FieldRename.snake, explicitToJson: true)
  const factory MyState({@Default(0) int counter,}) = _MyState;
  // const factory MyState.initial({@Default(0) int counter}) = Initial;
  // const factory MyState.loading() = Loading;
  // const factory MyState.one() = One;
  // const factory MyState.two() = Two;

  factory MyState.fromJson(Map<String, dynamic> json) =>
      _$MyStateFromJson(json);
}

class MyStateNotifier extends StateNotifier<MyState> {
  MyStateNotifier() : super(MyState());

  Future<void> one() async {
    await Future.delayed(Duration(seconds: 5));
    state.copyWith(counter: 1);
  }
}

Что мне нужно изменить, чтобы copyWith стал доступен в первом фрагменте?

2 ответа

Решение

Только свойства, общие для всех конструкторов, будут генерировать метод, как указано в документации README.

      You also can use copyWith with properties defined on all constructors...

Представьте, что у вас есть экземпляр Loading, какой метод вы ожидаете от этого? У него нет свойств, следовательно, у него не может быть никаких методов, поэтому не может быть и объединение всех типов.

Однако вы можете использовать сопоставление с образцом для вызова copyWith на экземплярах правильного типа.

В вашем примере будет работать что-то вроде этого:

      MyState myState = ...;

myState.maybeMap(
    initial: (v: Initial) => v.copyWith(counter: v.counter + 1),
    orElse: () => ...,
);

Или используя when:

      MyState myState = ...;

myState.when(
    (int counter) => MyState.initial(counter + 1),
    loading: () => loading,
    one: () => one,
    two: () => two,
);

вы можете получить доступ к методу copyWith, выполните преобразование типа:

`if (состояние CurrentState) {final myState = состояние как CurrentState}

myState.copyWith (...)`

Другие вопросы по тегам