dart-modern-syntax について
Dart開発者向けに、Dart 3.xの新しい構文を例とともに解説するスキルです。Dart 3.12の実験的なプライマリコンストラクターも取り上げます。
主な機能
- 01プライベートな名前付きパラメーターの解説
- 02ゼロコストの拡張型の紹介
- 03未使用要素向けワイルドカードの提示
- 04レコードとパターンマッチの実例
- 05実験的なプライマリコンストラクターの紹介
活用シーン
- 01コードで新しいDart構文を採用
- 02拡張型でドメイン値をラップ
- 03レコードやオブジェクトを分解
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ dhruvanbhalara/ skills --skill dart-modern-syntaxインストール後、Claude Code で/dart-modern-syntaxを入力して読み込まれたか確認します。
詳細
モダンな Dart 構文(Dart 3.0 - 3.12+)
Dart 3.x で導入された最新の構文機能を使って、クリーンで簡潔、型安全かつ高度に最適化されたコードを書きましょう。
目次
プライベートな名前付きパラメーター
Dart 3.12 で導入
Dart では、コンストラクターの名前付きパラメーターを使って、プライベートフィールドを直接初期化できるようになりました。これにより、初期化リストで手動代入する必要がなくなります。
使用方法
- 名前付きコンストラクターパラメーターを宣言する際は、プライベートフィールド名の前に
this.を付けます。 - コンパイラーは呼び出し箇所で先頭のアンダースコア(
_)を自動的に取り除きます。
class User {
final String _name;
final int _age;
// Initializing private fields directly
User({
required String this._name,
required int this._age,
});
String get name => _name;
int get age => _age;
}
void main() {
// Call site does NOT include the underscore
final user = User(name: 'Alice', age: 30);
print(user.name); // Alice
}
拡張型
Dart 3.3 で導入
拡張型は、基底となる表現型をラップする、コンパイル時のみ存在するラッパークラスです。標準クラスとは異なり、実行時にメモリー上でラッパーオブジェクトを割り当てないため、オーバーヘッドのない抽象化を実現します。
ルールとパターン
- 実行時の割り当てによるオーバーヘッドなしで、既存の型に新しいインターフェースを公開します。
extension type Name(RepresentationType value)を使って宣言します。- パフォーマンスが重視される API、ドメイン固有の ID ラッパー、または JS 相互運用オブジェクトのラップに使用します。
// Exposes a zero-cost wrapper around an integer
extension type Id(int value) {
// Add custom helper methods
bool get isValid => value > 0;
}
// Wrapping a list to restrict available methods
extension type IntList(List<int> list) {
int get head => list.first;
void printSummary() {
print('Length: ${list.length}, Head: $head');
}
}
void main() {
final myId = Id(42); // Zero overhead, compiled directly to 42
print(myId.isValid); // true
}
未使用要素のワイルドカード
Dart 3.7 で導入
ワイルドカード _ を使って、未使用の要素を表せます。これにより、リンターの警告を防ぎ、変数やインポートを意図的に無視していることを、ほかの開発者(および AI エージェント)に明確に示せます。
ワイルドカードのスコープ
- 未使用のパラメーター:コールバック内で
_(ネストする場合は__、___)を使用します。 - 未使用のローカル変数:副作用を発生させるためだけに必要な場合は、変数を
_として宣言します。 - 未使用のインポート:パッケージの初期化処理を名前を束縛せずに実行するには、インポート名として
_を指定します。
import 'package:init_library/init.dart' as _;
void processItems() {
final items = ['apple', 'banana', 'orange'];
// Wildcards in list mapping
final indexed = items.mapIndexed((index, _) => 'Item $index');
// Wildcard for unused exception variable
try {
performDangerousTask();
} catch (_) {
print('Failed to perform task.');
}
}
レコードとパターンマッチング
Dart 3.0 で導入
レコードを使うと、独自クラスを作る手間をかけずに、関数から複数の値を返せます。パターンマッチングを使うと、それらの値を取り出したり、オブジェクトをすっきりと分解したりできます。
構文上のベストプラクティス
- 位置指定レコード:
(double, double) getCoordinates() => (37.77, -122.41); - 名前付きレコード:
({String name, int age}) getDetails() => (name: 'Bob', age: 25); - 分解代入:一致する構造に直接代入します。
// 1. Positional Record Destructuring
final (lat, lng) = getCoordinates();
// 2. Named Record Destructuring
final (name: userName, age: userAge) = getDetails();
// 3. Object Destructuring with Patterns
if (user case User(name: final name, age: > 18)) {
print('$name is an adult');
}
プライマリコンストラクター
Dart 3.12 で導入(実験的)
プライマリコンストラクターを使うと、ほかのモダンな言語と同様に、フィールドの宣言と代入を自動的に行う簡潔な構文でクラスを定義できます。
// Shorthand for immutable data structures
class Point(int x, int y);
// Equivalent to:
// class Point {
// final int x;
// final int y;
// Point(this.x, this.y);
// }
コメント
Markdown 対応