TypeScriptで可変長引数をマスター!10選サンプルコード入門

TypeScriptのロゴと可変長引数のイメージ図TypeScript
この記事は約25分で読めます。

【サイト内のコードはご自由に個人利用・商用利用いただけます】

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

基本的な知識があればサンプルコードを活用して機能追加、目的を達成できるように作ってあります。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を凌駕する現役のプログラマチームによって監修されています。

サイト内のコードを共有する場合は、参照元として引用して下さいますと幸いです

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

はじめに

TypeScriptは、JavaScriptのスーパーセットとして知られ、強い型システムと高度な機能を持つプログラミング言語です。

中でも「可変長引数」という機能は、関数の引数に柔軟性を持たせるために使用されます。

今回は、TypeScriptでの可変長引数の使い方を、実用的な10のサンプルコードを通して詳しく解説します。

初心者から中級者まで、この記事を通じてTypeScriptの魅力を深く理解し、日々のプログラミング作業に役立てていただけることを願っています。

それでは、TypeScriptの可変長引数を一緒にマスターしましょう!

●TypeScriptの基礎知識

○TypeScriptとは?

TypeScriptは、Microsoftが開発した静的型付けのプログラミング言語です。

JavaScriptとの互換性を保持しつつ、静的型チェックやインターフェース、ジェネリクスなどの機能を備えています。

これにより、大規模なアプリケーションの開発や、バグの早期発見、コードのリファクタリングが容易になります。

○可変長引数とは?

可変長引数は、関数が任意の数の引数を受け取ることができる機能を指します。

JavaScriptにもこの機能は存在しますが、TypeScriptでは型の安全性も考慮しながら使用することができます。

具体的には、関数の引数に「…」(スプレッド構文)を使用することで、複数の引数を一つの配列として受け取ることができます。

●TypeScriptでの可変長引数の使い方

○サンプルコード1:基本的な可変長引数の関数

このコードでは、数値の可変長引数を受け取り、その合計を計算するシンプルな関数を表しています。

この例では、スプレッド構文を使用して数値を任意の数だけ受け取り、reduceメソッドを使って合計しています。

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

const result = sum(1, 2, 3, 4, 5);
console.log(`合計値は${result}です。`);

このコードを実行すると、「合計値は15です。」という結果が表示されます。

このように、可変長引数を活用することで、関数の引数の数を柔軟に変更することができます。

○サンプルコード2:配列として受け取る

このコードでは、文字列の可変長引数を受け取り、その内容を一つの文字列として連結する関数を表しています。

この例では、スプレッド構文とjoinメソッドを使って文字列を連結しています。

function concatenate(...strings: string[]): string {
    return strings.join(' ');
}

const concatenatedString = concatenate("TypeScript", "は", "素晴らしい");
console.log(concatenatedString);

このコードを実行すると、「TypeScript は 素晴らしい」という結果が得られます。

可変長引数を使うことで、関数の処理内容に合わせて柔軟に引数の数や型を変更することができます。

○サンプルコード3:可変長引数を組み合わせて関数を作る

TypeScriptは、JavaScriptに厳格な型システムを導入した言語として注目を浴びています。

その中で、可変長引数をうまく活用することで、さまざまなシチュエーションでの柔軟な関数定義が可能となります。

ここでは、TypeScriptの可変長引数を組み合わせた関数の作成方法について、具体的なサンプルコードを交えて解説します。

このコードでは、可変長引数と通常の引数を組み合わせて関数を作成する方法を表しています。

この例では、最初の引数として文字列を受け取り、その後の可変長引数で数値を任意の個数だけ受け取り、その合計値を返す関数を定義しています。

function combineAndSum(name: string, ...numbers: number[]): string {
  // 可変長引数で受け取った数値を合計する
  let sum = numbers.reduce((acc, curr) => acc + curr, 0);
  // 引数の名前と合計値を組み合わせた文字列を返す
  return `${name}の合計値は${sum}です。`;
}

// コメント: 関数の実行例
let result = combineAndSum("山田", 10, 20, 30, 40, 50);

このコードを実行すると、”山田の合計値は150です。”という結果を得ることができます。

注意点として、可変長引数は必ず最後の引数として定義する必要があります。

最初や中間の引数として可変長引数を使用することはできませんので、この点をおさえておくと、予期せぬエラーを避けることができます。

また、このような組み合わせは、特定のパラメータに対して追加の情報を受け取るような場面で役立ちます。

例えば、商品の名前とその商品に関連するタグのリストを受け取る関数など、さまざまな応用例を考えることができます。

function productWithTags(productName: string, ...tags: string[]): string {
  // 商品名とタグを組み合わせた文字列を返す
  return `${productName}: ${tags.join(", ")}`;
}

let tagResult = productWithTags("テレビ", "家電", "4K", "液晶");

上記のコードでは、”テレビ: 家電, 4K, 液晶”という文字列が得られます。

このように、特定の情報に加えて、それに付随する情報をリストとして受け取りたい場面で、可変長引数は非常に有効です。

○サンプルコード4:可変長引数を持つアロー関数

JavaScriptの開発に慣れている方にはお馴染みのアロー関数ですが、TypeScriptでももちろん利用することができます。

アロー関数はシンタックスが短く、thisの振る舞いも固定されているため、特定のケースで非常に便利です。

さて、アロー関数での可変長引数の使い方を見てみましょう。

このコードではアロー関数を使って、数字の可変長引数を受け取り、それらの合計を返す関数を表しています。

この例では、数字をいくつでも渡すことができ、それらの合計値を取得することができます。

// 可変長引数を持つアロー関数
const sum: (...numbers: number[]) => number = (...args) => {
  // reduceを使って合計を計算
  return args.reduce((acc, cur) => acc + cur, 0);
}

// 使用例
const result = sum(1, 2, 3, 4, 5);
console.log(`合計値は${result}です。`);  // 合計値は15です。

このコードを試すと、「合計値は15です。」という結果が得られるでしょう。

このように、アロー関数でも可変長引数をスムーズに取り扱うことができます。

特にショートハンドの形式で関数を記述する場面や、コールバック関数として関数を渡す場面で、アロー関数の利用は非常に有効です。

●応用:TypeScriptの可変長引数でよく使われるテクニック

○サンプルコード5:可変長引数とデフォルト引数

TypeScriptでは、関数の引数にデフォルト値を設定することも可能です。

この特徴を可変長引数と組み合わせることで、さらに強力な関数を作成することができます。

このコードでは、文字列の可変長引数を受け取り、それらを結合して1つの文字列を返す関数を表しています。

この例では、可変長引数とデフォルト引数を組み合わせて、引数が渡されなかった場合のデフォルトの文字列を設定しています。

// 可変長引数とデフォルト引数を持つ関数
const concatenateStrings = (separator = '-', ...strings: string[]) => {
  return strings.join(separator);
}

// 使用例
const concatResult = concatenateStrings(' ', 'TypeScript', '可変長引数', 'マスター');
console.log(concatResult);  // TypeScript 可変長引数 マスター

このコードを試すと、「TypeScript 可変長引数 マスター」という結果が得られるでしょう。

セパレータとしてスペースを指定しているので、それを使って文字列が結合されています。

○サンプルコード6:可変長引数を持つクラスメソッド

JavaScriptやTypeScriptでのクラスは、オブジェクト指向のプログラミングを実現するための非常に有力な手段として知られています。

今回は、TypeScriptのクラスの中で、可変長引数をどのように活用できるのかを具体的なサンプルコードを交えて解説します。

このコードでは、商品の名前と価格を管理する「Product」というクラスを作成しています。

このクラスのメソッド「addProducts」は、可変長引数を使って複数の商品を一度に追加する機能を持っています。

この例では、商品の名前を複数引数として受け取り、それを内部の配列に追加しています。

class Product {
  products: string[] = [];

  // 可変長引数を持つクラスメソッド
  addProducts(...newProducts: string[]): void {
    this.products = [...this.products, ...newProducts];
    // 新しく追加された商品名を内部の配列に統合する
  }

  displayProducts(): void {
    console.log(this.products);
    // 現在の商品名の配列を表示する
  }
}

const myProduct = new Product();
myProduct.addProducts("りんご", "ばなな", "みかん");
myProduct.displayProducts();

上記のコードを実行すると、コンソールに「[“りんご”, “ばなな”, “みかん”]」と表示されます。

このように、可変長引数を使うことで、一度に複数の商品をクラスの配列に追加することができるのです。

TypeScriptの可変長引数を活用することで、より柔軟なコードを書くことが可能となります。

特に、データを管理するクラスメソッドを設計する際に、可変長引数は非常に有効です。

応用例として、価格も同時に管理したい場合、次のようにコードを拡張することができます。

class AdvancedProduct {
  products: {name: string, price: number}[] = [];

  addProductsWithPrice(...newProducts: {name: string, price: number}[]): void {
    this.products = [...this.products, ...newProducts];
    // 新しく追加された商品名と価格を内部の配列に統合する
  }

  displayProducts(): void {
    for(const product of this.products) {
      console.log(`${product.name}: ¥${product.price}`);
      // 商品名と価格を表示する
    }
  }
}

const myAdvancedProduct = new AdvancedProduct();
myAdvancedProduct.addProductsWithPrice({name: "りんご", price: 100}, {name: "ばなな", price: 120}, {name: "みかん", price: 80});
myAdvancedProduct.displayProducts();

このコードでは、商品名と価格をオブジェクトの形で持ち、それを可変長引数として受け取ることで、商品名と価格を同時にクラスの配列に追加することができます。

上記のコードを実行すると、コンソールにそれぞれの商品の名前と価格が表示されるでしょう。

こうした方法を取り入れることで、TypeScriptでのプログラミングがより洗練され、生産性も向上します。

特に、大規模なアプリケーションを開発する際に、可変長引数の恩恵は大きいです。

○サンプルコード7:可変長引数を活用した計算関数

可変長引数は、任意の数の引数を受け取る関数を作成する際に非常に役立ちます。

ここでは、TypeScriptで可変長引数を使用して、任意の数の数字の合計を計算する関数を表しています。

この例では、sumという関数を定義し、可変長引数を使用して複数の数字を受け取り、それらの合計値を返しています。

function sum(...numbers: number[]): number {
    // 引数として与えられた数字を合計する
    return numbers.reduce((acc, val) => acc + val, 0);
}

// 使用例
const total = sum(10, 20, 30, 40);
console.log(`合計値は${total}です。`); // 合計値は100です。

このコードでは、sum関数内で...numbersという可変長引数を定義しています。

このnumbersは配列として扱われ、reduceメソッドを使って、配列内の数字の合計を計算しています。

実際にこのコードを実行すると、「合計値は100です」という結果が得られます。

可変長引数を活用することで、関数の引数の数に柔軟性を持たせることができます。

特に、合計や平均など、複数の数値を取り扱う関数を定義する際には、この可変長引数のテクニックは大変便利です。

ただし、可変長引数を使用する際は、関数内で引数の取り扱いに注意が必要です。

例えば、関数内で引数を配列として操作する際には、適切なメソッドやロジックを選択することで、予期しないエラーやバグを避けることができます。

また、このsum関数は、引数が数値以外の場合には適切に動作しない点にも注意が必要です。

このような場合には、関数のオーバーロードや型ガードを導入することで、より堅牢な関数を実装することができます。

次に、可変長引数を使用して、任意の数の数字の平均を計算する関数を紹介します。

function average(...numbers: number[]): number {
    const total = numbers.reduce((acc, val) => acc + val, 0);
    return total / numbers.length;
}

// 使用例
const avg = average(10, 20, 30, 40);
console.log(`平均値は${avg}です。`); // 平均値は25です。

このコードでは、average関数内で、先ほど紹介したsum関数と同様のロジックで数字の合計を計算しています。

その後、合計値を引数の数(numbers.length)で割ることで、平均値を得ています。

この関数を実行すると、「平均値は25です」という結果が得られます。

○サンプルコード8:オブジェクトのマージ

TypeScriptでのプログラミングを進める中で、複数のオブジェクトを一つに結合する、いわゆるオブジェクトのマージが必要になることがあります。

この時、可変長引数を駆使することで、柔軟かつ簡潔にこのタスクを実現することが可能です。

下記のコードは、複数のオブジェクトを受け取り、それらを一つのオブジェクトに結合する関数を表しています。

この例では、可変長引数を活用し、任意の数のオブジェクトをマージすることができます。

function mergeObjects(...objs: object[]): object {
    return objs.reduce((prev, current) => {
        return { ...prev, ...current };
    }, {});
}

// 使用例
const obj1 = { a: 1, b: 2 };
const obj2 = { b: 3, c: 4 };
const obj3 = { d: 5 };

const merged = mergeObjects(obj1, obj2, obj3);
console.log(merged);  // 結果として { a: 1, b: 3, c: 4, d: 5 } が出力されます。

このコードでは、mergeObjects関数を定義しています。

関数内でreduceメソッドを使用して、複数のオブジェクトを一つに結合しています。

また、スプレッド構文(...)を使うことで、2つのオブジェクトを簡単に結合することができます。

実際に使用例を見ると、obj1, obj2, obj3の3つのオブジェクトをmergeObjects関数に渡して、これらを一つのオブジェクトにマージした結果が得られます。

結果を見ると、bのプロパティはobj2のものが上書きされていることが分かります。

このように、可変長引数とスプレッド構文を組み合わせることで、TypeScriptでのオブジェクトのマージが簡単かつ効率的に実現できます。

しかし、注意する点として、同じプロパティ名を持つオブジェクトが複数存在する場合、後ろに指定されたオブジェクトのプロパティが前のものを上書きすることがあります。

実際の開発の現場では、このようなオブジェクトのマージの挙動を理解して、適切に可変長引数を活用することで、より柔軟なプログラミングが実現できます。

特に、設定やオプションを持つ大規模なアプリケーションでの使用に適しています。

次に、この技術のカスタマイズ例として、特定のプロパティだけをマージする関数を考えてみましょう。

function mergeSpecificProps(propName: string, ...objs: object[]): object {
    return objs.reduce((prev, current) => {
        if (current[propName]) {
            prev[propName] = current[propName];
        }
        return prev;
    }, {});
}

// 使用例
const objA = { id: 1, name: "Taro" };
const objB = { id: 2, age: 25 };
const objC = { id: 3, address: "Tokyo" };

const mergedId = mergeSpecificProps("id", objA, objB, objC);
console.log(mergedId);  // 結果として { id: 3 } が出力されます。

この関数は、特定のプロパティ名を指定して、そのプロパティだけを複数のオブジェクトからマージすることができます。

これにより、特定のプロパティを中心にしたデータの統合や集約が可能となります。

○サンプルコード9:可変長引数を活用したイベントハンドラ

TypeScriptにおいて、イベントハンドラは頻繁に使用される箇所の1つと言えるでしょう。

特に、ある関数にさまざまなイベントハンドラを動的に追加する場面では、可変長引数の活用が大変有効です。

このコードでは、複数のイベントハンドラを追加する関数を表しています。

この例では、イベントリスナーの配列を作成し、それを元にイベントを追加しています。

type EventHandler = (event: Event) => void;

class EventManager {
    private handlers: EventHandler[] = [];

    addEventHandlers(...handlers: EventHandler[]): void {
        // イベントハンドラを追加する
        this.handlers.push(...handlers);
    }

    callHandlers(event: Event): void {
        // 全てのハンドラを呼び出す
        for (const handler of this.handlers) {
            handler(event);
        }
    }
}

const handler1: EventHandler = event => {
    console.log("ハンドラ1が実行されました。");
};

const handler2: EventHandler = event => {
    console.log("ハンドラ2が実行されました。");
};

const manager = new EventManager();
manager.addEventHandlers(handler1, handler2);
manager.callHandlers(new Event("test"));

上記のサンプルコードを実行すると、ハンドラ1が実行されました。ハンドラ2が実行されました。 というメッセージが順に出力されます。

これにより、可変長引数を使用して、動的にイベントハンドラを追加することが可能になります。

注意として、この方法は動的にイベントを追加する場面に特化しています。

固定的なイベントを処理する際には、通常のイベントリスナーの設定方法を用いるのが適しています。

また、このテクニックはTypeScriptの強力な型チェック機能と組み合わせることで、さまざまなイベントハンドラの型を一貫して管理することができます。

これにより、イベントハンドリングのコードの品質や安全性を向上させることが期待できます。

○サンプルコード10:型安全性を高めるための工夫

TypeScriptはJavaScriptに静的型チェックの機能を加えたプログラミング言語として広く知られています。

そのため、型に関連したバグをコンパイル時に検出し、実行前にエラーを修正することができます。

これにより、開発の効率とコードの信頼性を高めることができます。

今回は、このTypeScriptの型システムをさらに強固にするための工夫を、サンプルコードを通して詳しく解説していきます。

このコードでは、可変長引数の型安全性を向上させる方法を表しています。

この例では、関数に渡される引数の数と型を厳格に制限して、コンパイル時に型エラーを検出する方法を実装しています。

// 引数の数と型を厳格に制限する関数の例
function combineStrings(...args: [string, string, string]): string {
    return args.join('-');
}

// 正しく動作する例
let combined = combineStrings("Type", "Script", "Rocks"); // "Type-Script-Rocks"

// 型エラーの例(引数の数が不足している)
// let errorExample = combineStrings("Type", "Script"); 

// 型エラーの例(引数の型が異なる)
// let anotherError = combineStrings("Type", "Script", 123);

上記のcombineStrings関数では、引数として必ず3つの文字列を受け取るようにしています。

これにより、引数の数や型が異なる場合にコンパイル時にエラーを検出することができます。

実際にcombineStrings("Type", "Script", "Rocks");というコードを実行すると、”Type-Script-Rocks”という文字列が返されます。

一方、コメントアウトされているcombineStrings("Type", "Script");combineStrings("Type", "Script", 123);のようなコードを実行しようとすると、TypeScriptのコンパイラが型エラーを出力します。

このように、可変長引数を利用する際にも、引数の数や型を明示的に制限することで、意図しないエラーを予防し、型安全性を高めることができます。

特に大規模なプロジェクトや複数人での開発を行う場面では、このような型の厳格な制限は非常に役立ちます。

●注意点と対処法

TypeScriptで可変長引数を使用する際には、多くのメリットが得られる一方、いくつかの注意点が存在します。

適切に可変長引数を活用するためには、これらの注意点を把握し、対処法を学ぶことが大切です。

○可変長引数を使用する際の型の互換性

TypeScriptでは、関数の引数や返り値の型が重要です。

可変長引数を使用する場面でも、型の互換性を保つ必要があります。

このコードでは、可変長引数を使用して数値の配列を受け取り、それを文字列の配列に変換する関数を表しています。

この例では、数値の配列を受け取り、それをマッピングして文字列に変換しています。

function convertNumbersToStrings(...numbers: number[]): string[] {
    // 数値を文字列に変換する
    return numbers.map(num => num.toString());
}

この関数を使用すると、次のような結果が得られます。

const result = convertNumbersToStrings(1, 2, 3);
console.log(result);  // ["1", "2", "3"]

関数を実行すると、[“1”, “2”, “3”]という文字列の配列が出力されます。

○型を厳格にする

TypeScriptの強力な型システムを活用するためには、可変長引数の型を厳格に定義することが推奨されます。

このコードでは、特定の文字列のみを可変長引数として受け取る関数を表しています。

この例では、”apple”、”banana”、”cherry”のいずれかの文字列しか受け取らないようにしています。

function fruitsCollector(...fruits: ("apple" | "banana" | "cherry")[]): void {
    // 受け取ったフルーツを表示
    console.log(fruits);
}

しかし、この関数に無効な値を渡すと、TypeScriptの型チェッカーがエラーを報告します。

fruitsCollector("apple", "orange");  // エラー: "orange"は受け取れない型です。

“orange”は関数の型定義に含まれていないため、エラーが出力されます。

○関数のオーバーロードを使用する

時に、可変長引数を持つ関数に対して、異なる型の引数を許容したい場合があります。

このような場面では、関数のオーバーロードを利用すると、柔軟に型定義を行うことができます。

このコードでは、文字列または数値の可変長引数を受け取る関数を表しています。

この例では、関数のオーバーロードを使用して、異なる型の可変長引数を受け取る定義を複数作成しています。

function processItems(...items: string[]): string[];
function processItems(...items: number[]): number[];
function processItems(...items: (string | number)[]): (string | number)[] {
    return items;
}

この関数を使用すると、文字列または数値の配列を返すことができます。

const stringResult = processItems("A", "B", "C");
console.log(stringResult);  // ["A", "B", "C"]

const numberResult = processItems(1, 2, 3);
console.log(numberResult);  // [1, 2, 3]

関数を実行すると、それぞれ[“A”, “B”, “C”]と[1, 2, 3]が出力されます。

●カスタマイズ方法

TypeScriptの可変長引数は、非常に汎用性が高く、多くのシチュエーションで役立ちます。

しかし、それだけでなく、可変長引数をカスタマイズする方法も多々存在します。

ここでは、そのカスタマイズ方法をいくつかのサンプルコードとともに紹介していきます。

○特定の型だけを許容する可変長引数

このコードでは、文字列型のみを許容する可変長引数の関数を表しています。

この例では、文字列型の引数を複数受け取り、それを連結して返す関数を実装しています。

function concatStrings(...strings: string[]): string {
  // 引数で受け取った文字列を連結する
  return strings.join('');
}

上記の関数を使って、例えばconcatStrings("Type", "Script", "可変長", "引数")と呼び出すと、”TypeScript可変長引数”という文字列が返されます。

○可変長引数の制限を設ける

このコードでは、受け取る可変長引数の数を制限する例を表しています。

この例では、最大3つまでの数字を受け取り、その合計を返す関数を実装しています。

function sumUpToThreeNumbers(a: number, b?: number, c?: number): number {
  // 3つの数字を合計する
  return a + (b || 0) + (c || 0);
}

この関数を使用して、sumUpToThreeNumbers(10, 20)を呼び出すと、合計の30が返されます。

○可変長引数とオプション引数の組み合わせ

このコードでは、オプション引数と可変長引数を組み合わせた関数を表しています。

この例では、先頭の文字列に接尾語として可変長引数の文字列を追加して返す関数を表しています。

function addSuffixes(base: string, ...suffixes: string[]): string {
  // 可変長引数の文字列を接尾語として追加する
  return base + suffixes.join('');
}

この関数を使用して、addSuffixes("プログラミング", "は", "楽しい")と呼び出すと、”プログラミングは楽しい”という文字列が返されます。

まとめ

TypeScriptでの可変長引数は、初心者から中級者までのコーダーにとって非常に重要なテクニックの1つです。

この記事を通じて、その魅力や効果的な使い方を十分に理解できたことでしょう。

この記事が、第一歩として、あなたのTypeScriptスキルの向上に寄与する一助となれば嬉しく思います。

引き続き、プログラミングを楽しんでください。