関数引数の型チェックやテンプレートリテラルに役立つ!TypeScript 配列から文字列リテラル型への変換
TypeScript 配列から文字列リテラル型への変換
用途
この方法は、以下の様な場面で役立ちます。
- コードの型安全性と可読性を向上させたい場合
- 関数の引数や戻り値の型として、許可される文字列を厳密に定義したい場合
方法
typeof
演算子を使う
typeof
演算子を使って、配列の要素の型を取得できます。
const colors = ["red", "green", "blue"] as const;
type Color = typeof colors[number]; // "red" | "green" | "blue"
上記のように、as const
アサーションを使って配列を定数型にすると、typeof
演算子によって各要素の型がリテラル型になります。
Mapped Types
を使う
Mapped Types
を使って、配列の各要素を個別にリテラル型に変換できます。
type Color = {
[key in typeof colors[number]]: key;
};
// Color は { red: "red", green: "green", blue: "blue" } 型になる
上記のコードでは、key in typeof colors[number]
で配列の各要素をループし、key
変数に各要素の文字列リテラルを代入しています。
これらの方法を使って、TypeScript 配列から文字列リテラル型を生成できます。状況に合わせて適切な方法を選択してください。
- 配列の要素に
null
やundefined
が含まれる場合、生成される型にもそれらが含まれます。 - 配列の要素に重複がある場合、生成される型には重複も含まれます。
const colors = ["red", "green", "blue"] as const;
function getColor(color: Color): void {
// ...
}
getColor("red"); // OK
getColor("purple"); // エラー: "purple" は "red" | "green" | "blue" に含まれない
type Color = {
[key in typeof colors[number]]: key;
};
function getColor(color: Color): void {
// ...
}
getColor("red"); // OK
getColor("purple"); // エラー: "purple" は "red" | "green" | "blue" に含まれない
型エイリアスの使用
type Color = typeof colors[number]; // "red" | "green" | "blue"
function getColor(color: Color): void {
// ...
}
配列の要素の型チェック
typeof
演算子や Mapped Types
を使って生成された型は、in
演算子を使って要素の型チェックに使用できます。
const colors = ["red", "green", "blue"] as const;
if ("red" in colors) {
// ...
} else {
// ...
}
配列の要素の順序
上記の例では、配列の要素の順序は生成された型の順序に影響します。
const colors = ["green", "red", "blue"] as const;
type Color = typeof colors[number]; // "green" | "red" | "blue"
function getColor(color: Color): void {
// ...
}
getColor("red"); // OK
getColor("green"); // OK
getColor("blue"); // OK
reduce 関数を使う
const colors = ["red", "green", "blue"];
type Color = typeof colors.reduce((acc, color) => {
acc[color] = color;
return acc;
}, {} as Record<string, string>);
// Color は { red: "red", green: "green", blue: "blue" } 型になる
Union to Intersection 型を使う
Union to Intersection
型を使って、配列の要素の型を個別にリテラル型に変換し、それらを組み合わせて単一の型を作ることができます。
type Color = ("red" | "green" | "blue") & ("red" | "green" | "blue");
// Color は "red" | "green" | "blue" 型になる
テンプレートリテラルを使う
テンプレートリテラルを使って、配列の要素を個別にリテラル型に変換し、それらを組み合わせて単一の型を作ることができます。
type Color = `${typeof colors[0]}` | `${typeof colors[1]}` | `${typeof colors[2]}`;
// Color は "red" | "green" | "blue" 型になる
これらの方法は、typeof
演算子や Mapped Types
を使う方法よりも複雑ですが、より柔軟な型定義が可能になります。状況に合わせて適切な方法を選択してください。
注意点
- これらの方法は、TypeScript 4.0 以降でのみ使用できます。
上記の例では、Color
という型エイリアスを使って、生成された型をより分かりやすく命名しています。
type Color = typeof colors.reduce((acc, color) => {
acc[color] = color;
return acc;
}, {} as Record<string, string>);
function getColor(color: Color): void {
// ...
}
in
演算子を使って、生成された型の要素の型チェックに使用できます。
const colors = ["red", "green", "blue"];
if ("red" in colors) {
// ...
} else {
// ...
}
const colors = ["green", "red", "blue"];
type Color = typeof colors.reduce((acc, color) => {
acc[color] = color;
return acc;
}, {} as Record<string, string>);
function getColor(color: Color): void {
// ...
}
getColor("red"); // OK
getColor("green"); // OK
getColor("blue"); // OK
arrays string typescript