1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに

前回

TypeScriptの真骨頂は「静的型付け」だけではない。

文脈に応じて変化する“文脈依存の型推論”すなわち 制御フロー解析(Control Flow Analysis) こそが、TypeScriptの型システムを強力たらしめている。

本稿では以下の要素を中心に解説する:

  • 制御フロー解析とは何か?
  • 型の絞り込み(Type Narrowing)の具体例
  • 型ガードの設計手法

制御フロー解析とは

制御フロー解析とは、プログラムの“実行経路”を型システムが理解し、値の型を絞り込む機能である。

以下のようなコードがその典型である。

function printLength(value: string | null) {
  if (value !== null) {
    console.log(value.length); // ✅ TypeScriptは value が string と認識する
  }
}

このように if 文の条件をもとに TypeScript は value の型を string に絞り込んでいる。


型の絞り込み(Type Narrowing)

TypeScript は以下のような構文で自動的に型の絞り込みを行う:

typeof

function log(x: string | number) {
  if (typeof x === "string") {
    console.log(x.toUpperCase());
  } else {
    console.log(x.toFixed(2));
  }
}

instanceof

class Dog {
  bark() {}
}
class Cat {
  meow() {}
}
function speak(pet: Dog | Cat) {
  if (pet instanceof Dog) {
    pet.bark();
  } else {
    pet.meow();
  }
}

in 演算子

function move(animal: { fly: () => void } | { swim: () => void }) {
  if ("fly" in animal) {
    animal.fly();
  } else {
    animal.swim();
  }
}

これらは全て、TypeScriptの「文脈を読む」力に基づいている。


ユーザー定義型ガード(Type Predicate)

より高度な型絞り込みを実現するために、開発者が独自に型ガードを定義できる。

function isString(value: unknown): value is string {
  return typeof value === "string";
}

function handle(value: unknown) {
  if (isString(value)) {
    console.log(value.toUpperCase());
  }
}

この構文 value is string型述語(Type Predicate) であり、TypeScript に対して型情報を明示的に与えている。

実務では、複雑な型や外部データ(例:APIレスポンス)を扱う際に極めて有用である。


never型と制御フローの網羅性

never は、型の絞り込みが“すべて消費された”ときに現れる特殊な型である。

type Shape = { kind: "circle"; radius: number } |
             { kind: "square"; side: number };

function area(shape: Shape) {
  switch (shape.kind) {
    case "circle":
      return Math.PI * shape.radius ** 2;
    case "square":
      return shape.side ** 2;
    default:
      const _exhaustiveCheck: never = shape; // ❌ 新しい型が追加されるとコンパイルエラー
      return _exhaustiveCheck;
  }
}

このようにして「すべてのパターンを網羅していること」をコンパイル時に保証できる。


まとめ

技法 用途
typeof, instanceof, in 組み込み型ガードによる絞り込み
型述語関数 より厳密かつ再利用可能な型判定
never を使った網羅性保証 安全性と拡張性の担保

制御フロー解析は、TypeScriptの型システムの中核であり、型安全な設計を支える屋台骨である。

この仕組みを正しく理解し活用することで、実装の堅牢性と可読性を飛躍的に高めることができる。


次回は「ジェネリクス完全攻略:柔軟かつ安全な型抽象化の設計術」をテーマに、TypeScriptの汎用性を支える設計手法に迫る。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?