Skip to content

6.7 さらに高度な型

この節では、普段から頻繁に使用するわけではないものの、TypeScriptの表現力を極限まで高めるための非常に高度な型機能について表面をなぞる程度に解説します。

  • object: 「プリミティブ以外のすべて(オブジェクト)」を表す型です。単体ではプロパティにアクセスできないため不便ですが、HasToString & object のようにインターセクション型と組み合わせることで、「メソッドを持つがプリミティブではない値」に制限したい場合などに役立ちます。
  • never: 「当てはまる値が存在しない」ことを表す型です。never 型の引数を要求する関数は呼び出すことができず、また never 型を返す関数は「必ず例外を投げて大域脱出する(正常に終了しない)関数」を意味します。

6.7.2 型述語(ユーザー定義型ガード)

Section titled “6.7.2 型述語(ユーザー定義型ガード)”

typeof などの単純な条件ではなく、複雑なロジックで型の絞り込みを行いたい場合に自身で定義する特殊な関数です。

  • 構文: 戻り値の型として 引数名 is 型 または asserts 引数名 is 型 を指定します。
  • 危険性と責任: ユーザー定義型ガードは anyas と同じく型安全性を破壊し得る危険な機能です。関数内の絞り込みロジックが正しいかどうかはコンパイラではなくプログラマーが責任を持つ必要があります。
  • メリット: 危険な機能の中では最も「何を保証すべきか(ロジックの正当性)」が明確であり、any を使うくらいならユーザー定義型ガードで代替すべきです。

タプル型の中に ...(スプレッド構文)に似た要素を含めることができる機能です。

  • 構文例: [number, ...string[]] のように記述し、「最初の要素が number で、それ以降は0個以上の string が続く配列」を表現できます。
  • 応用: [string, ...NSN, string] のように、既存のタプル型(NSN)を展開して新しいタプル型を作ることも可能です。

既存の型のプロパティ名(ユニオン型など)をループ処理のように展開し、新しいオブジェクト型を作り出す機能です。

  • 構文例: {[P in K]: T}
  • 挙動: ユニオン型 K(例: "apple" | "orange")の各要素 P に対して、型 T(例: number)を持つプロパティを生成します。

型の条件分岐を行う機能で、TypeScriptの「型レベルプログラミング」を支える強力な仕組みです。

  • 構文: X extends Y ? S : TXY の部分型ならば S 型、そうでなければ T 型)。
  • Union Distribution: X がユニオン型の場合、条件分岐がそれぞれの型に分配されて評価されるという特殊な性質を持ちます。

6.7.6 組み込みの型を使いこなす

Section titled “6.7.6 組み込みの型を使いこなす”

高度な mapped typesconditional types を自身で書かなくても、標準ライブラリにはよく使われる便利な型(ユーティリティ型)があらかじめ用意されています。

  • オブジェクトの加工:
    • Readonly<T>: すべてのプロパティを読み取り専用(readonly)にする。
    • Partial<T>: すべてのプロパティをオプショナル(?)にする。
    • Required<T>: すべてのプロパティを必須(オプショナルを外す)にする。
    • Pick<T, K>: 指定したプロパティ K のみを抜き出す。
    • Omit<T, K>: 指定したプロパティ K を除外する。
  • ユニオン型の加工:
    • Extract<T, U>: ユニオン型 T のうち、U に当てはまるものだけを抽出する。
    • Exclude<T, U>: ユニオン型 T から、U に当てはまるものを除外する。
    • NonNullable<T>: 型 T から nullundefined を除外する。