どうも、SupabaseでDevRelをしているタイラーです!
12月9日にFlutter公式Twitterアカウントより2023年の中頃までにDart 3がリリースされ、Flutterもそれに移行することが発表されましたね。
Flutter's secret sauce is Dart. By mid 2023 we'll take a big step together with Dart 3.
— Flutter (@FlutterDev) December 8, 2022
Learn how we are preparing for the next major release, where Dart only supports sound null safety, and get a preview of the new features.
Read the blog by @MiSvTh → https://t.co/VArkDwIVHg pic.twitter.com/iozxTC4z7C
今回はそんなDart 3で新しくレコード型という型が追加されるのですが、これが便利なので紹介させてください。
*ここで書いていることはまだ開発中の機能もあるのでもしかしたら変更になることもあるかもしれません。あくまで「こんな雰囲気の機能がやってくるんだ」くらいの感じで読んでいただけたら幸いです。
Record型の基礎
Dartでは今まで複雑な型を持つデータを定義する際にいちいちクラスを定義しなくてはならなかったのですが、このレコード(Record)型の登場で毎回クラスを定義する必要がなくなり、TypeScriptなど他の言語に近い感覚で開発をすることができるようになりました。また、他の言語で目にするTuple的な使い方もできるようになっています。
レコードは()
を使って書き、また引数の定義の仕方と同じで{}
でプロパティを囲うことでそのパラメーターをnamed parameterにすることができます。
// Positional argumentのみを使った例
(int myNumber, String myName) data = (1, 'Jon');
final myNumber = data.$0; // Positional argumentは`$[index]`の書き方でアクセスする
final myName = data.$1;
// Positional argumentとnamed parameterを混ぜた例
(int myNumber, {String myName}) data = (1, myName: 'Jon');
final myNumber = data.$0;
final myName = data.myName; // Named parameterは普通にそのパラメーター名でアクセスできる
実例
これを使うとコードをスッキリ書くことができるシチュエーションがあったりします。
例えば、パジネーション機能を実装するときにロードしたデータ、現在のページ、総ページ数の三つの値をAPIから引っ張ってきて返すような関数があったとしましょう。Dart 2ではこんな感じで書けると思います。
class PaginatedData {
final List<Item> items;
final int currentPage;
final int totalPages;
PaginatedData({
required this.items,
required this.currentPage,
required this.totalPages,
});
}
Future<PaginatedData> getPaginatedData(int currentPage) async {
// APIリクエストを投げるなどしてデータを引っ張ってくる
return PaginatedData(
items: items,
currentPage: currentPage,
totalPages: totalPages,
);
}
ここの例で言うPaginatedData
は特にクラスとして意味はなくただ単に3つの値をいっぺんに返すためだけに作られたクラスです。Dartで開発をしているとこのように複数の値を返すためだけのクラスが増えがちです。しかし、新しくできたレコード型を使うとこんな風にスッキリ書くことができます。
Future<({ List<Item> items, int currentPage, int totalPages })>
getPaginatedData(int currentPage) async {
// APIリクエストを投げるなどしてデータを引っ張ってくる
return (
items: items,
currentPage: currentPage,
totalPages: totalPages,
);
}
余計なクラスがなくなりだいぶコードがスッキリした感じがありますね。値は一度関数の戻り値を変数に受け取り、それのプロパティにアクセスすることできます。
final data = await getPaginatedData(currentPage);
final items = data.items;
final currentPage = data.currentPage;
final totalPages = data.totalPages;
これも悪くはないのですが、実はDestructuringという機能を使い一発でこれら三つの変数を取り出すこともできます。
final (:items, :currentPage, :totalPages) = await getPaginatedData(currentPage);
この一行だけでitems
, currentPage
, totalPages
という変数が作られ、それぞれ値が入ってくる形になります。
全体的に使い勝手はTypeScriptのオブジェクトとだいぶ類似していますね。昨今はBackendの構築でTypescriptを触っている人も多いかと思うのでだいぶこのアップデートは嬉しいのではないでしょうか!
レコード型の詳しい仕様はこちらに書いてあるので興味がある方は見てみてください。
また、DartのDevチャンネルではすでにDart 3を試すことができますので気になる方は触ってみてください!