もうif-elseにさよなら!TypeScriptでスマートな型別分岐 〜 分岐処理をもっとスマートに
TypeScriptにおける特定の型によるスイッチ
具体的な使用方法
function getLength(value: string | number): number {
switch (typeof value) {
case 'string':
return value.length;
case 'number':
return value.toString().length;
default:
return 0;
}
}
const strLength = getLength('Hello, World!'); // 13
const numLength = getLength(100); // 3
この例では、getLength
関数は、引数 value
の型に応じて、文字列の長さまたは数値の長さを返します。typeof
演算子を使用して、value
の型を検査し、対応するケースに処理を分岐させています。
型ガードの使用
TypeScript 3.7以降では、switch
文内で型ガードを使用することができます。型ガードは、評価対象の値の型をより詳細に絞り込むための構文です。これにより、より安全で柔軟な条件分岐が可能になります。
function getLengthV2(value: unknown): number {
if (typeof value === 'string') {
return value.length;
} else if (typeof value === 'number') {
return value.toString().length;
} else {
return 0;
}
}
const strLength = getLengthV2('Hello, World!'); // 13
const numLength = getLengthV2(100); // 3
上記の例では、getLengthV2
関数は、型ガードを使用して、value
が文字列であるかどうか、または数値であるかどうかをより明確に判断しています。これにより、コードの可読性と保守性が向上しています。
- 保守性の向上: コード変更時の影響範囲を把握しやすくなり、メンテナンスが容易になります。
- コードの可読性: 従来の
if-else
分岐よりも、条件分岐のロジックをより分かりやすく表現できます。 - 型安全性:
switch
文は、各ケースで処理される値の型を厳密にチェックするため、実行時エラーのリスクを低減できます。
Example 1: Checking for Primitive Types
function getDataType(value: unknown): string {
switch (typeof value) {
case 'string':
return 'String';
case 'number':
return 'Number';
case 'boolean':
return 'Boolean';
case 'object':
return 'Object';
default:
return 'Unknown';
}
}
const strData = getDataType('Hello'); // 'String'
const numData = getDataType(100); // 'Number'
const boolData = getDataType(true); // 'Boolean'
const objData = getDataType({ name: 'John Doe' }); // 'Object'
const unknownData = getDataType(null); // 'Unknown'
In this example, the getDataType
function determines the data type of the provided value
using a switch
statement. It checks for common primitive types (string
, number
, boolean
) and objects, and returns a corresponding string representing the data type.
Example 2: Handling Enum Values
enum Color {
Red,
Green,
Blue,
Yellow
}
function getColorName(color: Color): string {
switch (color) {
case Color.Red:
return 'Red';
case Color.Green:
return 'Green';
case Color.Blue:
return 'Blue';
case Color.Yellow:
return 'Yellow';
default:
return 'Invalid Color';
}
}
const redColor = getColorName(Color.Red); // 'Red'
const greenColor = getColorName(Color.Green); // 'Green'
const blueColor = getColorName(Color.Blue); // 'Blue'
const yellowColor = getColorName(Color.Yellow); // 'Yellow'
const invalidColor = getColorName(10); // 'Invalid Color'
This example demonstrates using a switch
statement to handle enum values. The getColorName
function takes a Color
enum value as input and returns the corresponding color name. It uses a switch
statement to match the provided color
value against the enum members and returns the corresponding string representation.
Example 3: Utilizing Type Guards
function getLengthOrArea(value: unknown): number {
if (typeof value === 'string') {
return value.length;
} else if (typeof value === 'number') {
if (value >= 0) {
return Math.sqrt(value); // Assume it's a square area
} else {
return -1; // Invalid area for negative numbers
}
} else {
return 0;
}
}
const strLength = getLengthOrArea('Hello, World!'); // 13
const numLength = getLengthOrArea(10); // 10 (square root of 10)
const negativeNum = getLengthOrArea(-5); // -1
const invalidData = getLengthOrArea({}); // 0
In this example, the getLengthOrArea
function utilizes type guards to handle different types of input values. It first checks for string
and number
types using typeof
operator. For strings, it returns the length. For positive numbers, it assumes it's a square and returns the square root. For negative numbers, it returns -1 (invalid area). For any other type, it returns 0.
if-else分岐
最も基本的な方法は、if-else
分岐を使用することです。各ケースを個別にチェックし、対応する処理を実行します。
function getLength(value: string | number): number {
if (typeof value === 'string') {
return value.length;
} else if (typeof value === 'number') {
return value.toString().length;
} else {
return 0;
}
}
この方法はシンプルで分かりやすいですが、ケースが増えると冗長になり、可読性が低下する可能性があります。
型ガード付きif文
TypeScript 3.7以降では、if
文内で型ガードを使用することができます。これにより、より安全で柔軟な条件分岐が可能になります。
function getLengthV2(value: unknown): number {
if (typeof value === 'string') {
return value.length; // 型ガードにより 'value' は文字列であることが保証される
} else if (typeof value === 'number') {
return value.toString().length; // 型ガードにより 'value' は数値であることが保証される
} else {
return 0;
}
}
この方法は、従来のif-else
分岐よりも、より明確で型安全な条件分岐を実現できます。
パターンマッチングライブラリ
import { match } from 'ts-pattern-matching';
function getLength(value: unknown): number {
return match(value)
.with('string', (s: string) => s.length)
.with('number', (n: number) => n.toString().length)
.otherwise(() => 0);
}
この方法は、より複雑なパターンマッチングを可能にし、コードをより簡潔に記述することができます。
適切な方法の選択
どの方法が最適かは、具体的な状況によって異なります。
- 複雑なパターンマッチング: パターンマッチングライブラリは、より複雑な条件分岐をより簡潔に記述することができます。
- 型安全性を重視: 型ガード付き
if
文は、より安全で型安全な条件分岐を実現できます。 - シンプルなケース:
if-else
分岐が最もシンプルで分かりやすい方法です。
それぞれの方法の利点と欠点を理解し、状況に応じて適切な方法を選択することが重要です。
typescript