TypeScriptにおけるinferキーワードの理解
Daniel Hayes
Full-Stack Engineer · Leapcell

TypeScriptのinfer
キーワードは、条件型で型を推論するために使用されます。これは、複雑な型を扱う際に特に便利で、型を抽出または変換することができます。
基本的な使用法
infer
キーワードは、条件型の中でのみ使用でき、通常はジェネリクスおよびextends
キーワードと組み合わせて使用されます。構文は次のとおりです。
type Moment<T> = T extends infer U ? U : never;
ここで、T extends infer U
は、型T
を推論し、それをU
に割り当てることを意味します。型推論が成功した場合、U
は推論された型になります。
これを使用して、さまざまな型を推論できます。いくつかの例を挙げます。
type Moment<T> = T extends infer U ? U : never; type StringType = Moment<string>; // string type NumberType = Moment<number>; // number type UnionType = Moment<string | number>; // string | number interface User { name: string; age: number; } type UserType = Moment<User>; // User
これらの例では、Moment<T>
は基本的に型T
を変換や処理なしで返すだけです。これは主に、条件型と型推論の基本的な使用法を示すためのものです。
一般的な例
関数の戻り値の型を抽出する
関数型があり、その戻り値の型を抽出したいとします。これは次のようにできます。
type GetReturnType<T> = T extends (...args: any[]) => infer R ? R : never; type ExampleFunction = (x: number, y: string) => boolean; type ReturnTypeOfExampleFunction = GetReturnType<ExampleFunction>; // boolean
上記のコードでは:
T extends (...args: any[]) => infer R
: これは、T
が関数型であるかどうかを確認します。(...args: any[])
は、関数が任意の数の引数を受け入れることができることを意味します。infer R
:T
が関数型の場合、infer R
は関数の戻り値の型を推論し、それを型変数R
に割り当てます。? R : never
:T
が関数型の場合、推論された戻り値の型R
が返されます。それ以外の場合は、never
が返されます。
配列の要素の型を抽出する
infer
を使用して、配列の要素の型を抽出することもできます。
type GetArrayElementType<T> = T extends (infer U)[] ? U : never; type Moment = string[]; type Example1Array = Array<string>; type ElementTypeOfExampleArray = GetArrayElementType<Moment>; // string type ElementTypeOfExample1Array = GetArrayElementType<Example1Array>; // string
ここでは、T extends (infer U)[]
を使用して、配列の要素の型U
を推論します。T
がstring[]
であるため、U
はstring
になります。
string[] extends (infer U)[ ]
infer
宣言は、条件型のextends
句内でのみ許可され、infer
で宣言された型変数はtrueブランチ内でのみ利用可能であることに注意することが重要です。
高度な例
Promiseの値の型を抽出する
Promise
型がある場合、その解決された値の型を抽出できます。
type GetPromiseValueType<T> = T extends Promise<infer U> ? U : never; // Example type ExamplePromise = Promise<number>; type ValueTypeOfExamplePromise = GetPromiseValueType<ExamplePromise>; // number
上記のコードでは:
T extends Promise<infer U>
: これは、T
がPromise
型であるかどうかを確認します。infer U
:T
がPromise
型の場合、infer U
はPromise
の解決された値の型を推論し、それをU
に割り当てます。? U : never
:T
がPromise
型の場合、推論された値の型U
が返されます。それ以外の場合は、never
が返されます。
関数のパラメータの型を抽出する
関数型からパラメータの型を取得する必要がある場合があります。infer
を使用すると、これを実現できます。
type GetParameters<T> = T extends (...args: infer P) => any ? P : never; type ExampleFunction = (a: number, b: string) => void; type Params = GetParameters<ExampleFunction>; // [number, string]
上記のコードでは:
T extends (...args: infer P) => any
: これは、T
が関数型であるかどうかを確認します。infer P
:T
が関数型の場合、infer P
は関数のパラメータの型を推論し、それらをP
に割り当てます。? P : never
:T
が関数型の場合、推論されたパラメータの型P
が返されます。それ以外の場合は、never
が返されます。
コンストラクタのパラメータの型を抽出する
infer
を使用して、クラスコンストラクタのパラメータの型を抽出することもできます。
type ConstructorParameters<T> = T extends new (...args: infer P) => any ? P : never; class ExampleClass { constructor(public a: number, public b: string) {} } type Params = ConstructorParameters<typeof ExampleClass>; // [number, string]
条件型における複雑な推論
条件型内で複雑な推論ロジックを使用する必要があるとします。
type IsArray<T> = T extends (infer U)[] ? U : never; type IsFunction<T> = T extends (...args: any[]) => infer R ? R : never; type ExtractType<T> = T extends any[] ? IsArray<T> : T extends (...args: any[]) => any ? IsFunction<T> : T; // Example type ArrayType = ExtractType<string[]>; // string type FunctionReturnType = ExtractType<() => number>; // number type DefaultType = ExtractType<boolean>; // boolean
このコードでは:
type ExtractType<T> = T extends any[] ? IsArray<T> : T extends (...args: any[]) => any ? IsFunction<T> : T;
T extends any[] ? IsArray<T>
:T
が配列型の場合、配列の要素型を抽出するIsArray
を返します。T extends (...args: any[]) => any ? IsFunction<T>
:T
が関数型の場合、関数の戻り値の型を抽出するIsFunction
を返します。T
:T
が配列型でも関数型でもない場合、T
自体を返します。
まとめ
infer
キーワードは、条件型の中で使用され、別の型から新しい型変数を推論します。これにより、型チェック中に特定のサブタイプまたはプロパティを抽出して利用できるようになり、TypeScriptの型システムの表現力と柔軟性が向上します。簡単に言えば、infer
は複雑な型から目的の部分を自動的に抽出するのに役立ちます。
Leapcellは、Node.jsプロジェクトをホストするための最適な選択肢です。
Leapcellは、Webホスティング、非同期タスク、およびRedisのための次世代サーバーレスプラットフォームです:
多言語サポート
- Node.js、Python、Go、またはRustで開発。
無制限にプロジェクトを無料でデプロイ
- 使用量に応じてのみ支払い—リクエストや料金は不要です。
比類なきコスト効率
- アイドル料金なしの従量課金制。
- 例:25ドルで、平均応答時間60ミリ秒で694万リクエストをサポートします。
合理化された開発者エクスペリエンス
- 簡単なセットアップのための直感的なUI。
- 完全に自動化されたCI / CDパイプラインとGitOps統合。
- 実行可能な洞察のためのリアルタイムのメトリックとロギング。
簡単なスケーラビリティと高パフォーマンス
- 高い同時実行性を容易に処理するための自動スケーリング。
- 運用上のオーバーヘッドはゼロ—構築に集中するだけです。
詳細については、ドキュメントをご覧ください!
Xでフォローしてください:@LeapcellHQ