Null安全のその先へ:`List.whereType` が最強である技術的根拠
DartのSound Null Safetyは、単なる「Nullポインタ例外の防止」ではありません。コンパイラが型システムを静的に保証し、ランタイムの型チェックを最小化するための強力な武器です。
多くのエンジニアが、`List
本稿では、Dartの型システムを掌握し、パフォーマンスと安全性を両立させる『`whereType
—
1. なぜ `where((e) => e != null)` は不完全なのか
まず、以下のコードを見てください。
final List
// 一般的なアプローチ
final nonNullList = nullableList.where((e) => e != null).toList();
// この時点での nonNullList の型は List
このコードの問題点は、Dartの型推論が「このリストにnullは含まれない」という事実を理解できない点にあります。結果として、後続の処理で `nonNullList[0]` にアクセスするたびに、コンパイラは `String?` 型として扱い、不必要なNullチェックを強いてきます。
型安全性を担保するために `nonNullList.map((e) => e!)` と書くのは論外です。それは型システムに対する敗北であり、コードの記述量を増やすだけの愚策です。
—
2. `whereType`:コンパイラを味方につける最適解
`whereType
final List
// 魔法のような一行
final List
// ここで cleanList は List
print(cleanList.runtimeType); // List
なぜこれが「極限」の選択なのか
1. 静的型の昇格 (Type Promotion): `whereType
2. VM最適化: Dart VMの実装において、`whereType` は内部的に `Type` オブジェクトの照合を行うよう最適化されています。不要なラムダ式(クロージャ)の生成・実行コストを削減し、CPUパイプラインを汚しません。
3. 可読性と宣言的プログラミング: 「Nullを除去したい」のではなく「`String` だけが欲しい」という意図が型名として明示されます。これは設計の意図をコード自体に語らせる、最もクリーンな手法です。
—
3. 実践:API連携における堅牢なデータ変換
Web APIから受け取るレスポンスには常に不確定要素が伴います。特に「配列の一部が壊れていてnullが混入する」ケースは現場で頻発します。
以下は、保守性を最大化するプロダクションコードのパターンです。
class User {
final int id;
final String name;
User(this.id, this.name);
}
// APIからの不安定なレスポンス
final dynamic rawData = [
{‘id’: 1, ‘name’: ‘Alice’},
null,
{‘id’: 2, ‘name’: ‘Bob’},
];
void main() {
// ステップ1: Nullを弾きつつ、Map型のみを安全に抽出
// ステップ2: 型安全にインスタンス化
final users = rawData
.whereType
print(users); // [User, User]
}
この実装の美しさは、エラーを握りつぶすのではなく、型システムに乗らないものを静かに除外できる点にあります。`rawData` がどんなに汚れていても、`users` リストは常に `List
—
最後に:型を信じる者が、Dartを制する
DartのNull安全は、書き手に対して「曖昧さを排除せよ」と絶えず問いかけてきます。
`whereType
明日からのコードレビューで、`where((e) => e != null)` を見つけたら、迷わず `whereType
DartのVMがそのコードをどう解釈するか、常にその先を想像し続けましょう。それが、伝説的なアーキテクトへの唯一の道です。