言語ごとの差を超えて、全体として次の方向へ進化しています。
16.1 暗黙から明示へ
旧来:
値がnullかもしれない
型が実行するまで分からない
未定義プロパティを自由に追加できる
エラーは特殊な戻り値で表す
現代:
Nullable型を付ける
Union型で候補を列挙する
プロパティを宣言する
Result型や例外型で失敗を表す
16.2 可変から不変へ
旧来:
変数やオブジェクトを自由に変更する
現代:
デフォルトは不変
変更箇所だけ明示
変更後は新しい値を作る
16.3 継承からコンポジションへ
旧来:
巨大なクラス階層
親クラスから実装を継承
現代:
小さなインターフェース
Trait・Protocol
依存性注入
機能の合成
16.4 文字列定数から型付き状態へ
旧来:
status = "active"
タイプミスが可能です。
status = "acitve"
現代:
enum Status {
Active,
Suspended,
}
型が許可された状態を限定します。
16.5 nullからOptionへ
旧来:
Userまたはnull
現代:
Some(User)またはNone
欠損を通常値とは異なるケースとして明示します。
16.6 例外だけから型付きエラーへ
旧来:
何が投げられるか実装を読まないと分からない
現代:
Result<User, UserLoadError>
失敗の可能性が型に現れます。
16.7 条件分岐からパターンマッチへ
旧来:
ifやswitchを重ねる
フィールドを手動で確認する
現代:
データの型と構造を同時に照合する
未処理ケースをコンパイラが検出する
16.8 コールバックからasync/awaitへ
旧来:
loadUser(id, function (user) {
loadOrders(user, function (orders) {
// ネスト
});
});
現代:
const user = await loadUser(id);
const orders = await loadOrders(user);
非同期処理を同期処理に近い見た目で書けます。