@freezed copyWith 缺少密封类

pth*_*fan 2 dart flutter flutter-freezed

在以下代码片段中,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);
  }
}
Run Code Online (Sandbox Code Playgroud)

但是,当我删除密封类时,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);
  }
}
Run Code Online (Sandbox Code Playgroud)

我需要更改什么才能使 copyWith 在第一个片段中可用?

Ren*_*ato 8

只有所有构造函数共有的属性才会生成copyWith方法,如README 文档中所述。

We can use copyWith with properties defined on all constructors...
Run Code Online (Sandbox Code Playgroud)

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

但是,您可以使用模式匹配来调用copyWith正确类型的实例。

在你的例子中,这样的事情会起作用:

MyState myState = ...;

myState.maybeMap(
    initial: (v: Initial) => v.copyWith(counter: v.counter + 1),
    orElse: () => ...,
);
Run Code Online (Sandbox Code Playgroud)

或者使用when

MyState myState = ...;

myState.when(
    (int counter) => MyState.initial(counter + 1),
    loading: () => loading,
    one: () => one,
    two: () => two,
);
Run Code Online (Sandbox Code Playgroud)