🎉

freezed 2.0 の変更内容を眺める

2022/04/21に公開

概要

気づいたら freezed 2.0 がリリースされていたので Changelog を眺めた内容をメモしておきます

変更内容

  • Breaking: freezed_annotation no-longer exports the entire package:collection

これまで import 'package:freezed_annotation/freezed_annotation.dart'; を書いてれば package:collection の API も使えていましたが、特定のものしか公開されなくなったので何かしら使っている場合はちゃんと自分でpubspec.yamlに依存を追加した方が良さそう
https://pub.dev/packages/collection

  • Removed @Freezed(maybeMap: ) & @Freezed(maybeWhen: ) in favor of a separate:
(map: FreezedMapOptions(...), when: FreezedWhenOptions(...))

Freezedアノテーションに設定できた、maybeMapおよびmaybeWhenの生成有無を設定する項目がなくなり、代わりのパラメータが用意されたようです。
もともと使用したことがなかったので私の環境では特に影響なさそう。(Changelogで初めて存在を知った)

  • Breaking: Freezed now converts Lists/Maps/Sets into UnmodifiableListView/UnmodifiableMapView/UnmodifiableSetView. This can be disabled for one class by specifying @Freezed(makeCollectionsUnmodifiable: false). Alternatively, this can be configured inside the build.yaml file

List/Map/Set が自動的に Immutable なオブジェクトに変換されるようになります。
以下のようなことをしているとエラーになるので要注意です。


class TodoState with _$TodoState {
  const factory TodoState({
    ([]) List<Todo> tasks,
  }) = _TodoState;
}

final state = TodoState();
// Unsupported operation: Cannot add to an unmodifiable list
state.tasks.add(Todo('ゴミ捨て'));

回避するには、@Freezed(makeCollectionsUnmodifiable: false)を付与するか、ちゃんと Immutable で扱うだと思います。

var state = TodoState();
// OK
state = state.copyWith(
  tasks: state.tasks + [Todo('ゴミ捨て')],
);

List の Immutable を仕組みで強制できるのは嬉しいですが、もともと List を Mutable で扱ってしまっているプロジェクトではそこそこ影響がありそうです。
郷に入っては郷に従うで、徐々に Immutable にリファクタリングしていった方が良い気がします。

  • Added parameters of @Freezed to customize the generated code. This includes: fromJson, toJson, map, when, equal, toStringOverride, copyWith.

@Freezed アノテーションにいろいろなパラメータが追加されていて、生成するコードをカスタマイズできるようです。
便利そうですが、パッと使いたいケースが思い浮かばなかったので記憶の片隅へ…

  • Added @unfreezed as a variant to @freezed, for mutable classes

Immutable なオブジェクトを生成する@freezedに対し、Mutableなオブジェクトを生成する@unfreezedが追加されました。
@freezedを使った場合、全ての変数がfinalとなり書き換え不可ですが@unfreezedを使った場合はfinalをつけた項目だけがfinalとなり他は書き換えが可能となります。
代わりに、書き換えが可能ですのでconst句は使えなくなります。

class Person with _$Person {
  factory Person({
    required String name,
    required final int age,
  }) = _Person;
}

final person = Person(name: 'kiyosuke', age: 23);
person.name = 'john'; // OK
person.age = 24; // NG

また、equalsなども生成されない様子です。
個人的には、freezedを使っていてMutableなオブジェクトを生成したいと思ったことはないですが必要に駆られることがあれば使ってみたいと思います。

Discussion