言語ごとの差を超えて、全体として次の方向へ進化しています。

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);

非同期処理を同期処理に近い見た目で書けます。