LoginSignup
88
92

More than 1 year has passed since last update.

TypeScriptの型で型の条件分岐ができる?(Conditional Types)

Last updated at Posted at 2022-01-18

タイトルがよくわからなくなっちゃいました:innocent:
個人の備忘録的に記事にいたします。

構文例

以下の構文を例にしてみます。

type First<T extends unknown[]> = T extends never[] ? never : T[0]

この First<>T が never[] の場合、never型 になります。

それ以外は、T[]の最初だけの型 になります。

これは、TypeScript の Conditional Types と呼ばれるものです。

解説

コードの以下の部分に注目いたします。

T extends never[] ? never : T[0]

ここでの T は Generic で受け取る型になります。

そして、T extends never[] ? の部分は、
T が never[] を継承しているかどうかの判定になります。

そこから後は 真の場合 : 偽の場合 です。

三項演算子と同様の記法ですね。

条件分岐地獄

ちなみに、この条件分岐をつなげていくこともできます。

以下は公式にあった例です。

type TypeName<T> = T extends string
  ? "string"
  : T extends number
  ? "number"
  : T extends boolean
  ? "boolean"
  : T extends undefined
  ? "undefined"
  : T extends Function
  ? "function"
  : "object";

type T0 = TypeName<string>; // "string"
type T1 = TypeName<"a">; // "string"
type T2 = TypeName<true>; // "boolean"
type T3 = TypeName<() => void>; // "function"
type T4 = TypeName<string[]>; // "object"

おっっふ!!!!

一緒によく使われるinferについて

最後は、Conditional Types とよく一緒に使われる、inferについてです。

とても簡単に言うと、「Conditional Types の構文の中で型をキャプチャする機能」です。

以下、構文例です。

type Awaited<T extends Promise<unknown>> = T extends Promise<infer R> ? R : never

解説

上記の解説です。

まず、以下の部分です。

T extends Promise<infer R> ?

T extends Promise なので、T が Promise型であるかどうかの判定になります。

Promise<infer R>
以下の例を参考にしてみます。

type Hoge = Promise<string>
type Foo = Awaited<Hoge> // "string"

この場合は、Promise<string><string> の部分を R にキャプチャしています。

そして、Promise型であるため、R を返している、つまり string になります。

ドキュメント

以上になります。

88
92
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
88
92