TypeScriptで条件付き型をマスターする

利用可能な言語 :

TypeScriptの条件付き型… それらはカメレオンのように、コードのニーズに応じて形を変え、適応します!基本的な型にはすでに慣れているかもしれませんが、条件付き型はそれを次のレベルへと引き上げます。型付けのスーパーヒーローのように、状況に応じて適応するスマートな型だと考えてください。では、TypeScriptコードに魔法を加える準備をしましょう!🧙‍♂

なぜ条件付き型を使うのか?🧐

TypeScriptでは、すべてが整然と整理され、厳密に型付けされていることが理想的です。しかし時には、特定の条件に基づいて適応する型が必要になります。入力パラメータに応じてstringnumberのどちらかを返す関数があるとしましょう。😱 条件付き型がなければ、各ケースを手動で管理する必要があり、それはすぐに面倒になってしまいます!幸運なことに、条件付き型は型付け忍者のように柔軟性と応答性をもたらします。🥷

基本:条件付き型の構文 🧩

条件付き型は型のための三項演算子のようなものです。例を見てみましょう:

typescript
1type IsString<T> = T extends string ? "It's a string" : "It's not a string";

この例では、IsStringTstringかどうかをチェックする条件付き型です。もしそうであれば"It's a string"を、そうでなければ"It's not a string"を返します。単純そうですが、より高度なケースで何ができるか見てみましょう!

実践例:設定に基づく型の適応 🛠️

設定パラメータを受け取り、その設定に応じて異なる型を返す必要がある関数を想像してみましょう。条件付き型はこのような魔法に最適です ✨!

コード例

typescript
1type Config = {
2 mode: 'simple' | 'detailed';
3};
4
5type Response<T extends Config> = T['mode'] extends 'simple'
6 ? { data: string }
7 : { data: string; details: string[] };
8
9function fetchData<T extends Config>(config: T): Response<T> {
10 if (config.mode === 'simple') {
11 return { data: 'Simplified data' } as Response<T>;
12 } else {
13 return {
14 data: 'Full data',
15 details: ['detail1', 'detail2'],
16 } as Response<T>;
17 }
18}
19
20const simpleConfig = { mode: 'simple' };
21const detailedConfig = { mode: 'detailed' };
22
23const resultSimple = fetchData(simpleConfig); // { data: "Simplified data" }
24const resultDetailed = fetchData(detailedConfig); // { data: "Full data", details: [...] }

この例では、Response<T>mode"simple""detailed"かに基づいて型を適応させます。fetchData(simpleConfig)dataのみを含むオブジェクトを返し、fetchData(detailedConfig)detailsも含むという魔法が起こります。便利ですよね?

ネストされた条件付き型:アラカルト型付け 🧇

そこで止める必要はありません!条件付き型をネストして、さらに正確なケースを処理することもできます!modeだけでなく、ユーザーが認証されているかどうかに基づいて型を適応させたいとしましょう。高度な型のジャグリングの準備はできていますか?🎢

typescript
1type UserResponse<
2 T extends Config,
3 Authenticated extends boolean,
4> = Authenticated extends true
5 ? T['mode'] extends 'simple'
6 ? { data: string }
7 : { data: string; details: string[] }
8 : { error: 'Not authenticated' };
9
10function fetchUserData<T extends Config, Authenticated extends boolean>(
11 config: T,
12 isAuthenticated: Authenticated,
13): UserResponse<T, Authenticated> {
14 if (!isAuthenticated) {
15 return { error: 'Not authenticated' } as UserResponse<T, Authenticated>;
16 }
17 if (config.mode === 'simple') {
18 return { data: 'Simplified data' } as UserResponse<T, Authenticated>;
19 } else {
20 return {
21 data: 'Full data',
22 details: ['detail1', 'detail2'],
23 } as UserResponse<T, Authenticated>;
24 }
25}
26
27const resultAuthSimple = fetchUserData(simpleConfig, true); // { data: "Simplified data" }
28const resultAuthDetailed = fetchUserData(detailedConfig, true); // { data: "Full data", details: [...] }
29const resultNotAuth = fetchUserData(detailedConfig, false); // { error: "Not authenticated" }

ここでは、UserResponsemodeisAuthenticatedという2つの基準に基づいて型を適応させます。結果として、すべての可能なケースをカバーする超精密な型付けが実現します!

inferを使用した高度な条件付き型:型推論 🕵️‍♂️

高度なテクニックの準備はできていますか?TypeScriptには条件付き型で使用する特別なキーワードinferがあります。これにより、条件付き型の中で直接型を推論できます。複雑な型から情報を抽出するのに便利です!

inferの例

typescript
1type ReturnTypeOfFunction<T> = T extends (...args: any[]) => infer R
2 ? R
3 : never;
4
5function getHello(): string {
6 return 'Hello, world!';
7}
8
9type HelloReturnType = ReturnTypeOfFunction<typeof getHello>; // 結果: string

ここでは、ReturnTypeOfFunctioninfer Rを使用して関数の戻り値の型を推論します。この例では、getHelloは文字列を返すため、HelloReturnTypestring型になります。

結論 🎉

TypeScriptの条件付き型は、コードのスーパーパワーのようなものです。動的な型を作成し、厳密な型付けを維持しながら、コードをよりシンプルにすることができます。同僚を感動させる準備はできていますか?これらの条件付き型を試して、TypeScriptコードを構造化する新しい方法を発見しましょう!🚀

もう曖昧な型付けには言い訳はありません—条件付き型を使えば、TypeScriptコードは事実上バレットプルーフになります!👌

この記事を共有する


Sébastien Timoner

Sébastien TIMONER

リードデベロッパー
カスタム開発エキスパート
Aix-en-Provence, France

Web開発とチームマネジメントのエキスパートとして、高性能なデジタルソリューションの作成と最適化を専門としています。React.js、Node.js、TypeScript、Symfony、そしてIoT向けのZephyr OSなどの最新技術における豊富な専門知識を活かし、offroadLabsにて様々な業界の企業向けに、設計から本番環境までの複雑なSaaSおよびIoTプロジェクトの成功を確実にします。

offroadLabsでは、技術的専門知識と協力的なアプローチを組み合わせたカスタム開発サービスを提供しています。革新的なSaaSソリューションの作成、Zephyr OSを使用したIoTシステムの開発、既存アプリケーションの近代化、またはチームのスキルアップ支援など、各プロジェクトの特定のニーズに合わせた堅牢で高性能なソリューションの提供に取り組んでいます。

エクサンプロヴァンス地域またはフルリモートでのプロジェクトに対応可能です。