【保存版】TypeScriptでコードをもっと読みやすく!定数からUnion型を生成する方法
TypeScriptで定数から文字列リテラルのUnion型を定義する方法
例
const STATUS_OK = "OK";
const STATUS_ERROR = "ERROR";
type Status = typeof STATUS_OK | typeof STATUS_ERROR; // Status は "OK" | "ERROR" のいずれかの型になる
function handleStatus(status: Status) {
if (status === STATUS_OK) {
console.log("処理が成功しました。");
} else if (status === STATUS_ERROR) {
console.error("処理が失敗しました。");
} else {
console.error("予期しないステータスです:", status);
}
}
handleStatus(STATUS_OK); // OK という文字列を渡す
handleStatus(STATUS_ERROR); // ERROR という文字列を渡す
handleStatus("UNKNOWN"); // 型エラーが発生する
この例では、STATUS_OK
と STATUS_ERROR
という定数を定義し、それぞれ "OK"
と "ERROR"
という文字列を代入しています。
次に、typeof
演算子を使用して、これらの定数から型を取得します。 typeof STATUS_OK
は "OK"
型、typeof STATUS_ERROR
は "ERROR"
型になります。
最後に、|
演算子を使用して、これらの型をUnion型 Status
に結合します。 Status
型は "OK"
または "ERROR"
のいずれかの型になります。
handleStatus
関数は、Status
型の引数を受け取ります。 関数内では、status
変数に対して STATUS_OK
と STATUS_ERROR
を比較し、対応する処理を実行します。
STATUS_OK
または STATUS_ERROR
以外の文字列が渡された場合、else
ブロック内のコードが実行され、エラーメッセージが出力されます。
利点
- コードの保守性が向上します。 コードを変更する際に、関連するすべての場所を修正する必要がなくなります。
- 型安全性が向上します。 コンパイル時に、誤った型の値が変数に代入されないようにチェックできます。
- コードの可読性が向上します。 変数に代入された文字列の意味が明確になります。
上記以外にも、文字列リテラルのUnion型を定義する方法があります。 例えば、
- 交差型を使用する
これらの方法は、状況に応じて使い分けることができます。
// 定数を定義する
const STATUS_OK = "OK";
const STATUS_ERROR = "ERROR";
const STATUS_WARNING = "WARNING";
// typeof 演算子を使用して定数から型を取得する
type Status = typeof STATUS_OK | typeof STATUS_ERROR | typeof STATUS_WARNING;
// Status 型の引数を受け取る関数
function handleStatus(status: Status) {
switch (status) {
case STATUS_OK:
console.log("処理が成功しました。");
break;
case STATUS_ERROR:
console.error("処理が失敗しました。");
break;
case STATUS_WARNING:
console.warn("警告があります。");
break;
default:
console.error("予期しないステータスです:", status);
}
}
// 関数を使用する
handleStatus(STATUS_OK); // OK という文字列を渡す
handleStatus(STATUS_ERROR); // ERROR という文字列を渡す
handleStatus(STATUS_WARNING); // WARNING という文字列を渡す
handleStatus("UNKNOWN"); // 型エラーが発生する
説明
このコードでは、以下のことを行っています。
STATUS_OK
、STATUS_ERROR
、STATUS_WARNING
という 3 つの定数を定義します。 それぞれ"OK"
、"ERROR"
、"WARNING"
という文字列を代入します。handleStatus
関数は、Status
型の引数を受け取ります。- 関数内では、
switch
ステートメントを使用して、status
変数の値を比較します。 - 各ケース内で、対応する処理を実行します。
default
ケースでは、status
変数が予期しない値である場合の処理を実行します。- コードの最後に、
handleStatus
関数をさまざまな引数で呼び出して、関数の動作を確認します。
- 交差型を使用すると、より複雑な型を定義できます。
enum
型を使用すると、同様の機能を実現できますが、enum
型は数値ベースの型であることに注意してください。- このコードは、TypeScript 3.0以降で使用できます。
// 列挙型を定義する
enum Status {
OK = "OK",
ERROR = "ERROR",
WARNING = "WARNING",
}
// 列挙型のメンバーを使用する
function handleStatus(status: Status) {
switch (status) {
case Status.OK:
console.log("処理が成功しました。");
break;
case Status.ERROR:
console.error("処理が失敗しました。");
break;
case Status.WARNING:
console.warn("警告があります。");
break;
default:
console.error("予期しないステータスです:", status);
}
}
handleStatus(Status.OK); // Status.OK という値を渡す
handleStatus(Status.ERROR); // Status.ERROR という値を渡す
handleStatus(Status.WARNING); // Status.WARNING という値を渡す
- 列挙型のメンバーには、値だけでなく、プロパティやメソッドを定義することもできます。
- 列挙型は、コードをより読みやすく、自己文書化することができます。
欠点
- 列挙型のメンバーは、後で変更するのが難しい場合があります。
- 列挙型のメンバーは、手動で定義する必要があります。
交差型は、2 つ以上の型のすべてのプロパティを持つ新しい型を定義するためのものです。 文字列リテラルの Union 型を定義するのにも使用できます。
// 交差型を定義する
type Status = { OK: "OK" } & { ERROR: "ERROR" } & { WARNING: "WARNING" };
// 交差型を使用する
function handleStatus(status: Status) {
switch (status.OK) { // Status.OK プロパティにアクセスする
case "OK":
console.log("処理が成功しました。");
break;
case "ERROR":
console.error("処理が失敗しました。");
break;
case "WARNING":
console.warn("警告があります。");
break;
default:
console.error("予期しないステータスです:", status);
}
}
handleStatus({ OK: "OK" }); // { OK: "OK" } というオブジェクトを渡す
handleStatus({ ERROR: "ERROR" }); // { ERROR: "ERROR" } というオブジェクトを渡す
handleStatus({ WARNING: "WARNING" }); // { WARNING: "WARNING" } というオブジェクトを渡す
- 交差型は、複雑な型を定義することができます。
- 交差型は、動的に生成された型を使用することができます。
- 交差型は、コードを冗長にする可能性があります。
- 交差型は、理解するのが難しい場合があります。
TypeScript で定数から文字列リテラルの Union 型を定義するには、いくつかの方法があります。 最適な方法は、特定の状況によって異なります。
- 動的に生成された型や複雑な型を使用したい場合は、交差型を使用する方法がおすすめです。
- コードをより読みやすく、自己文書化したい場合は、列挙型を使用する方法がおすすめです。
- コードを簡潔かつ読みやすくしたい場合は、定数と
typeof
演算子を使用する方法がおすすめです。
typescript string-literals typescript3.0