Derive union type from tuple/array values in TypeScript

2024-04-02

TypeScriptでタプル/配列の値からユニオン型を導出する方法

as 演算子を使う

最も簡単な方法は、as 演算子を使うことです。例えば、以下のコードでは、tuple の要素の型から MyUnion というユニオン型を導出しています。

const tuple: [string, number, boolean] = ['foo', 1, true];

type MyUnion = typeof tuple[number];

const value: MyUnion = 'foo'; // 型安全
const value2: MyUnion = 1; // 型安全
const value3: MyUnion = true; // 型安全

as 演算子は、タプル型だけでなく、配列型にも使用できます。

const array: string[] = ['foo', 'bar', 'baz'];

type MyUnion = typeof array[number];

const value: MyUnion = 'foo'; // 型安全
const value2: MyUnion = 'bar'; // 型安全
const value3: MyUnion = 'baz'; // 型安全

infer キーワードを使う

TypeScript 4.0以降では、infer キーワードを使って、より安全で柔軟な方法でユニオン型を導出することができます。

type MyUnion = infer T extends typeof tuple[number] ? T : never;

const value: MyUnion = 'foo'; // 型安全
const value2: MyUnion = 1; // 型安全
const value3: MyUnion = true; // 型安全

infer キーワードは、typeof tuple[number] の型パラメータ T に、タプル型の各要素の型を代入します。そして、T extends typeof tuple[number] ? T : never という条件式を使って、T がタプル型の要素の型のいずれかに一致する場合のみ、T をユニオン型の型として返します。

ReadonlyArray 型を使う方法もあります。

type MyUnion = ReadonlyArray<typeof tuple[number]>[number];

const value: MyUnion = 'foo'; // 型安全
const value2: MyUnion = 1; // 型安全
const value3: MyUnion = true; // 型安全

ReadonlyArray 型は、読み取り専用の配列型を表します。ReadonlyArray<typeof tuple[number]> は、タプル型の要素の型の読み取り専用配列型になります。そして、ReadonlyArray<typeof tuple[number]>[number] は、その配列型の要素の型になります。

これらの方法を使いこなすことで、タプル/配列の値からユニオン型を安全かつ効率的に導出することができます。状況に応じて適切な方法を選択してください。

補足

  • as 演算子は、TypeScript 2.7以降で使用できます。



as 演算子を使う

const tuple: [string, number, boolean] = ['foo', 1, true];

type MyUnion = typeof tuple[number];

const value: MyUnion = 'foo'; // 型安全
const value2: MyUnion = 1; // 型安全
const value3: MyUnion = true; // 型安全

console.log(value, value2, value3); // 'foo' 1 true

infer キーワードを使う

type MyUnion = infer T extends typeof tuple[number] ? T : never;

const value: MyUnion = 'foo'; // 型安全
const value2: MyUnion = 1; // 型安全
const value3: MyUnion = true; // 型安全

console.log(value, value2, value3); // 'foo' 1 true

ReadonlyArray 型を使う

type MyUnion = ReadonlyArray<typeof tuple[number]>[number];

const value: MyUnion = 'foo'; // 型安全
const value2: MyUnion = 1; // 型安全
const value3: MyUnion = true; // 型安全

console.log(value, value2, value3); // 'foo' 1 true



タプル/配列の値からユニオン型を導出するその他の方法

reduce 関数を使って、タプル/配列の各要素をユニオン型にまとめることができます。

const tuple: [string, number, boolean] = ['foo', 1, true];

type MyUnion = typeof tuple.reduce((acc, cur) => {
  acc |= cur;
  return acc;
}, 0);

const value: MyUnion = 'foo'; // 型安全
const value2: MyUnion = 1; // 型安全
const value3: MyUnion = true; // 型安全

console.log(value, value2, value3); // 'foo' 1 true

このコードでは、reduce 関数を使って、タプル/配列の各要素をビット演算子 | で結合しています。ビット演算子 | は、2つのオペランドのいずれか一方でも真であれば真を返します。

const tuple: [string, number, boolean] = ['foo', 1, true];

type MyUnion = [typeof tuple[number]] extends [infer T] ? T : never;

const value: MyUnion = 'foo'; // 型安全
const value2: MyUnion = 1; // 型安全
const value3: MyUnion = true; // 型安全

console.log(value, value2, value3); // 'foo' 1 true

このコードでは、concat 関数を使って、タプル/配列の各要素を1つの配列に結合しています。そして、spread 演算子を使って、結合された配列の要素をユニオン型に展開しています。

手動でユニオン型を定義する

上記の方法でうまくいかない場合は、手動でユニオン型を定義することができます。

type MyUnion = string | number | boolean;

const value: MyUnion = 'foo'; // 型安全
const value2: MyUnion = 1; // 型安全
const value3: MyUnion = true; // 型安全

console.log(value, value2, value3); // 'foo' 1 true

この方法は、コード量が最も少なくなりますが、型安全性を確保するためには、タプル/配列の要素の型を正確に記述する必要があります。


typescript


JavaScriptとTypeScriptにおけるオープンエンド関数引数

この例では、sum関数は. ..numbersという引数を受け取ります。...演算子は、渡された引数を配列に変換します。そのため、numbers変数には、呼び出し時に渡されたすべての数値が格納されます。TypeScriptでは、引数の型も指定できます。この例では、sum関数はnumber型の引数のみを受け取るように定義されています。...


Visual Studio CodeでTypeScript開発を快適に!.js.mapファイルを非表示にする4つの方法

Visual Studio CodeでTypeScriptプロジェクトを扱う際、.js. mapファイルが生成され、エクスプローラーに表示されることがあります。これらのファイルはソースコードのデバッグに役立ちますが、常に表示されていると煩わしいこともあります。...


最新JavaScriptフレームワークを駆使!React、TypeScript、WebpackでスマートなCSSモジュール開発

Webpack 設定ファイル (webpack. config. js) で、CSS モジュールを処理するためのローダーを構成する必要があります。上記の例では、style-loader と css-loader の 2 つのローダーを使用しています。...


共通型、型ガード、型パラメータ... TypeScript インデックスシグネチャでユニオン型を使いこなす

インデックスシグネチャは、オブジェクトのキーと値の型の関係を定義するものです。 例えば、以下のようなコードがあります。この例では、Person インターフェースは name と age という 2 つのプロパティを持ち、それぞれ string 型と number 型であることを定義しています。...


Angular KeyValue パイプでプロパティをソート/順序通りにイテレーションする方法

デフォルトのソートデフォルトでは、KeyValue パイプはキー順にアイテムをソートします。つまり、オブジェクトのキーがアルファベット順に表示されます。キー順でソートするには、ngFor ディレクティブの trackBy プロパティを使用できます。trackBy プロパティには、キーを取得する関数を指定します。...


SQL SQL SQL SQL Amazon で見る



TypeScriptでカスタム型と「typeof」を使いこなして、コードの読みやすさを向上!

この方法では、typeof演算子とin演算子を使用して、変数の型がカスタム型かどうかを判断します。上記の例では、isMyCustomTypeというユーザー定義型ガード関数を作成しています。この関数は、typeof演算子を使って引数の型がオブジェクトかどうかを判断し、in演算子を使ってオブジェクトにnameとageというプロパティが存在するかどうかを確認しています。