@freezed copyWith 丢失并密封 类

@freezed copyWith missing with sealed classes

在以下代码段中,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 可用?

只有所有构造函数共有的属性才会生成 copyWith 方法,如 README docs.

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

假设您有一个 Loading 的实例,您希望它有什么 copyWith 方法?它没有属性,因此它不能有任何 copyWith 方法,因此所有类型的 union 也不能。

但是,您可以使用模式匹配在正确类型的实例上调用 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(状态为当前状态){ final myState = 状态为 CurrentState }

myState.copyWith (...)`