関数は特定のタスクを実行するためのコードの集まりであり、入力(引数)を受け取り、処理を行い、結果(戻り値)を出力する構造です。TypeScriptでは、JavaScriptの関数に加えて、型安全性を提供する重要な機能があります。これにより、関数の引数と戻り値に型を指定することができ、コードの安全性と可読性が向上します。
TypeScriptは基本的にはJavascriptの上位互換言語なので、TypeScriptで関数を定義する方法もJavascriptと同様2つあります:関数宣言と関数式です。
ポイント 関数宣言
function add(x: number, y: number): number { return x + y; }
ポイント 関数式
const subtract = (x: number, y: number): number => { return x - y; };
基本的にはJavaScriptの関数を理解していれば、TypeScriptではそこに型の指定が追加されるだけで基本的な動作は全く同じ。「そもそも関数って何?」という方は、以下のページで1から詳しく解説しておりますので、まずは以下をご覧ください。
それでは、早速TypeScriptの関数の定義方法、実行、利用上の注意点をご説明していきます。
TypeScript:関数宣言
function functionName(parameter1: type, parameter2: type, ...): returnType { // 関数の本体 }
function
:関数を定義する際に使用するキーワード。functionName
:関数の名前。parameter1, parameter2, ...
:関数が受け取る引数。関数は複数の引数を受け取ることができ、それぞれの引数はコンマで区切らる。type
:引数の型。TypeScriptでは、number
,string
,boolean
などの基本的な型の他に、独自に定義した型やインターフェースも使用できます。returnType
:関数の戻り値の型。関数が値を返さない場合は、void
を使用。
サンプルコード 数値を2つ受け取り、その和を返す関数
function add(x: number, y: number): number { return x + y; }
この例では、add
関数は2つのnumber
型の引数x
とy
を受け取り、その和をnumber
型で返します。
引数が任意(オプション)の場合
JavaScriptと同様、関数の引数は任意にすることができます。任意の引数は、引数名の後に?
をつけて定義します。オプショナルな引数は、呼び出し時に省略可能です。
function greet(name: string, greeting?: string): string { return `${greeting || "Hello"}, ${name}!`; }
↑の例では、greet
関数は2つ目の引数greeting
をオプショナルにしています。greeting
が提供されない場合、デフォルトの挨拶"Hello"
が使用されます。
デフォルトパラメータ
関数の引数にはデフォルト値を設定することもできます。引数が省略された場合、デフォルト値が使用されます。
function greet(name: string, greeting: string = "Hello"): string { return `${greeting}, ${name}!`; }
↑の場合、greeting
引数にデフォルト値"Hello"
が設定されています。呼び出し時にgreeting
を省略すると、このデフォルト値が使われます。
TypeScript:関数式
関数式は関数を変数に割り当てる方法で、匿名関数(名前のない関数)を使用して定義されます。これは、JavaScriptの関数式の概念を型の安全性とともに拡張したものです。関数式は、即時実行が必要な場合や、コールバック関数として他の関数に渡す必要がある場合に特に便利です。
const myFunction = function(parameter1: type, parameter2: type, ...): returnType { // 関数の本体 };
const
:変数宣言。関数式を保持する変数を宣言するために使用。let
やvar
も使用可能ですが、再代入不可のconst
が推奨される。myFunction
:関数を参照する変数名。
アロー関数を用いた短縮形で記述することもできます。
参考 アロー関数とは?
const myFunction = (parameter1: type, parameter2: type, ...): returnType => { // 関数の本体 };
関数式の特徴と利点
基本的な関数宣言と比較して、関数式を用いる利点は以下の通り。ざっくり言えば、手軽にかつ簡潔に記述できる点が関数式のメリット。(ここらへんもJavaScriptと同様です!)
- 名前のない関数(匿名関数)
- 関数式は名前を持たないため、一時的な処理や即時実行関数に適しています。
- アロー関数
- より簡潔な構文と
this
の挙動が異なる点が特徴です。アロー関数内のthis
は、アロー関数が定義されたコンテキストを指します。
- より簡潔な構文と
- 型の安全性
- TypeScriptの型システムを利用することで、引数と戻り値に対する型の安全性が保証されます。
- 高階関数
- 関数を他の関数に引数として渡したり、関数から別の関数を戻り値として返すパターンに適しています。
TypeScript:関数の実行
TypeScriptで関数を実行する方法も基本的にはJavaScriptの関数の実行方法と同様です。関数を実行するには、関数名に続けて括弧()
を書き、括弧の中に必要な引数をコンマで区切って渡します。引数が不要な場合でも、括弧は必須です。
関数宣言の場合
関数宣言を使用して関数を定義した場合、その関数は定義されたスコープ内のどこからでも呼び出すことができます。
// 関数の定義 function greet(name: string): string { return `Hello, ${name}!`; } // 関数の実行 const message = greet("Alice"); console.log(message); // 出力: Hello, Alice!
関数式の場合
関数式で関数を定義した場合、その関数は関数式が割り当てられた変数を通じて呼び出します。
// 関数式の定義(アロー関数を使用) const add = (x: number, y: number): number => { return x + y; }; // 関数の実行 const sum = add(5, 7); console.log(sum); // 出力: 12
即時実行関数式 (IIFE)
即時実行関数式(Immediately Invoked Function Expression)は、定義された直後に自動的に実行される関数です。TypeScriptでのIIFEもJavaScriptと同様に書けますが、型安全性の利点があります。
// 即時実行関数式の例 ((name: string) => { console.log(`Hello, ${name}!`); })("Alice");
この例では、アロー関数を使用したIIFEが定義され、"Alice"
が引数として渡されています。この関数は、定義された直後に一度だけ実行されます。
高階関数の実行
高階関数(他の関数を引数として受け取る関数や、関数を戻り値として返す関数)も同様に実行できます。
// 高階関数の例 function repeat(times: number, action: (index: number) => void): void { for (let i = 0; i < times; i++) { action(i); } } // 高階関数の実行 repeat(3, (index) => { console.log(`This is iteration number ${index}`); });
↑の例では、repeat
関数は2つの引数を受け取ります:実行回数と、各反復で実行するアクションを定義する関数です。これらの例からわかるように、TypeScriptでの関数の実行は、関数の種類や定義方法にかかわらず、直感的で柔軟なものであることが分かります。
TypeScript:関数に関するテクニック
TypeScriptの関数を使いこなす上では基本的な定義や実行方法の理解に加えて、いくつかの重要な概念や機能を把握しておくと良いでしょう。ここからは、TypeScriptの型システムを活用し、より安全で保守しやすいコードを書くためにおさえておきたい重要ポイントをご説明します。
ジェネリック型
ジェネリック型を関数に適用することで、関数をより柔軟に再利用可能にすることができます。ジェネリック型を使用すると、関数が受け取る引数や返す戻り値の型を呼び出し時に指定できるようになります。
function identity<T>(arg: T): T { return arg; } let output = identity<string>("myString"); let outputNumber = identity<number>(100);
↑の例では、identity
関数は任意の型T
の値を受け取り、同じ型の値を返します。これにより、同一の関数構造を異なる型で使用することができます。
オーバーロード
TypeScriptでは関数のオーバーロードをサポートしており、同じ名前の関数を異なる引数の型や数で複数定義することができます。これにより、関数の引数に応じて異なる処理を実行することが可能になります。
function makeDate(timestamp: number): Date; function makeDate(m: number, d: number, y: number): Date; function makeDate(mOrTimestamp: number, d?: number, y?: number): Date { if (d !== undefined && y !== undefined) { return new Date(y, mOrTimestamp, d); } else { return new Date(mOrTimestamp); } }
この例では、makeDate
関数はタイムスタンプを受け取るバージョンと、月、日、年を個別に受け取るバージョンの2つの呼び出し方ができます。
タプルとデストラクチャリング
関数の引数や戻り値としてタプルを使用することで、複数の値を効率的に扱うことができます。また、デストラクチャリングを使うことで、これらの値を簡単に取り出すことができます。
function useState<T>(initialValue: T): [T, (newValue: T) => void] { let value = initialValue; const setValue = (newValue: T) => { value = newValue; }; return [value, setValue]; } const [counter, setCounter] = useState(0);
↑の例では、useState
関数は状態の値と、その状態を更新する関数をタプルとして返します。このようなパターンは、ReactのHooks APIで広く採用されています。
これらの概念を理解し、適切に活用することで、TypeScriptでの関数の使いこなし度が深まり、より複雑なアプリケーションの開発にも対応できるようになります。
スキルアップを手軽に!
話題のサブスク型プログラミングスクールをご紹介。
SAMURAI TERAKOYA
月額2,980円から始める-入会金不要/途中解約自由。無料体験プランからスタート可能!
飲み会1回分以下の料金で継続的なスキルアップを。
Freeks(フリークス)
月額10,780円でJavaScript、Pythonなどのカリキュラムが学び放題。
質問し放題&転職サポート制度あり。
ウズウズカレッジ/CCNAコース用
月額33,000円(税込)〜インフラエンジニアの登竜門「CCNA」取得を目指す。
コース受講→転職成功で【実質全額無料】(最大240,000円)