アルアカ - Arcadia Academia

Arcadia Academiaは「エンジニアリングを楽しむ」を合言葉に日本のデジタル競争力を高めることをミッションとするテックコミュニティです。

TypeScriptにおける関数の型付け

Featured image of the post

TypeScriptでは、関数に型を付けることで、引数や戻り値に対して静的型チェックが行えるようになり、コードの安全性と可読性が向上します。この記事では、関数の型付けに関する基本的な方法から、応用的なパターンまでを解説します。

1. 関数の基本的な型付け

TypeScriptでは、関数の引数戻り値に対して型を指定することができます。以下は、基本的な関数の型付けの例です。

function greet(name: string): string {
    return `Hello, ${name}!`;
}

console.log(greet("TypeScript")); // "Hello, TypeScript!"
引数の型付け

上記の例では、nameという引数にstring型を指定しています。関数を呼び出す際に、string型以外の値を渡すとコンパイルエラーになります。

greet(123); // エラー: 'number'型の引数は'string'型のパラメーターに割り当てられません。
戻り値の型付け

関数の戻り値にも型を指定できます。greet関数はstring型を返すことが明示されており、もし異なる型を返す場合はエラーが発生します。

function greet(name: string): number {
    return `Hello, ${name}!`; // エラー: 'string'型の値は'number'型に割り当てられません。
}

2. 関数の型推論

TypeScriptは関数の戻り値を自動的に推論するため、戻り値の型を省略することもできます。ただし、明示的に型を指定することで、コードがより明確になり、他の開発者が読みやすくなります。

function sum(a: number, b: number) {
    return a + b; // 戻り値は自動的にnumber型と推論される
}

3. オプショナル引数とデフォルト引数

関数の引数が必須でない場合、オプショナル引数デフォルト引数を使うことができます。

オプショナル引数

オプショナル引数は、引数の後ろに?を付けて定義します。この場合、引数を渡さなくてもエラーにはなりません。

function greet(name: string, age?: number): string {
    if (age) {
        return `Hello, ${name}! You are ${age} years old.`;
    }
    return `Hello, ${name}!`;
}

console.log(greet("Alice")); // "Hello, Alice!"
console.log(greet("Alice", 30)); // "Hello, Alice! You are 30 years old."
デフォルト引数

デフォルト引数は、引数に値が渡されなかった場合に使用するデフォルトの値を指定できます。

function greet(name: string = "Guest"): string {
    return `Hello, ${name}!`;
}

console.log(greet()); // "Hello, Guest!"
console.log(greet("Alice")); // "Hello, Alice!"

4. 関数型(Function Type)

関数の型自体を定義することもできます。関数型は、引数と戻り値の型を指定して、関数の型を表現します。

let add: (a: number, b: number) => number;

add = (x, y) => x + y;

console.log(add(2, 3)); // 5

この例では、add変数に対して「abnumber型で、戻り値もnumber型の関数」という型を指定しています。これにより、他の型の関数を代入しようとするとエラーになります。

add = (x: string, y: string) => x + y; // エラー: 型が一致しません

5. コールバック関数の型

コールバック関数を使用する際も、引数として渡す関数に型を指定することができます。これにより、期待されるコールバックの型を保証し、型の不一致によるエラーを防ぎます。

function map(array: number[], callback: (value: number) => number): number[] {
    return array.map(callback);
}

const result = map([1, 2, 3], (value) => value * 2);
console.log(result); // [2, 4, 6]

この例では、callback関数がnumber型の値を引数に取り、number型を返す関数であることが型定義で保証されています。

6. 可変長引数(Rest Parameters)

TypeScriptでは、関数に可変長引数を指定することができます。可変長引数を使うことで、関数が任意の数の引数を受け取れるようになります。

function sum(...numbers: number[]): number {
    return numbers.reduce((total, num) => total + num, 0);
}

console.log(sum(1, 2, 3)); // 6
console.log(sum(1, 2, 3, 4, 5)); // 15

...numbersは可変長引数を表しており、関数に渡された引数はnumber[]の配列として扱われます。

7. オーバーロード(関数の多重定義)

TypeScriptでは、同じ関数名で異なる引数型や戻り値型を持つ関数を定義することができます。これを関数のオーバーロードと呼びます。

function display(value: string): void;
function display(value: number): void;
function display(value: any): void {
    if (typeof value === "string") {
        console.log(`String: ${value}`);
    } else if (typeof value === "number") {
        console.log(`Number: ${value}`);
    }
}

display("Hello"); // String: Hello
display(123); // Number: 123

この例では、display関数がstring型またはnumber型の引数を受け取れることを示しています。実装部分では、typeofを使って型に応じた処理を行っています。

8. ジェネリクスを使った関数型

ジェネリクスを使うことで、関数に汎用的な型を付けることができます。これにより、異なる型の引数に対しても同じ関数ロジックを再利用できます。

function identity<T>(value: T): T {
    return value;
}

console.log(identity<string>("Hello")); // "Hello"
console.log(identity<number>(123)); // 123

この例では、Tという型パラメータを使用し、引数と戻り値が同じ型であることを保証しています。呼び出し時に型を明示することで、様々な型に対応した関数を作成できます。

まとめ

TypeScriptでは、関数に対して引数や戻り値の型を明確に指定することで、予期しないバグを防ぎ、より安全で保守性の高いコードを記述できます。基本的な引数や戻り値の型指定だけでなく、コールバック関数の型やオーバーロード、ジェネリクスを活用した柔軟な関数型の定義まで、TypeScriptの強力な型システムを使って関数の型付けを行いましょう。



▼ 目次