😉

Typescript 関数の理解を深める

に公開

日頃プログラミングをしていてTypescriptの関数について理解を深めたいなと思い記事を書きました。
内容は僕が理解不足だったり深めたい箇所がメインですのでそこをご了承いただけると嬉しいです!

void関数における早期returnについて

戻り値の型がvoidである関数においても、returnによる処理の中断が可能です。
この性質を活用することで、条件によって処理を早期に終了させ、不要なネストや処理の継続を避けることができます。

function doSomething(): void {
  if (someCondition) return;
  console.log("続行");
}

この例では、someConditionがtrueであればそれ以降の処理を行わずに関数を抜け、void型であることにより戻り値が不要なため、return;のように値なしでの中断が許容。

レビュアーからのコメントで早期リターン進められたのを思い出しました笑

分割代入を用いた関数パラメータの簡略化

関数にオブジェクトを渡す場合、分割代入を用いることでコードの簡潔性が向上します。
特に、オブジェクトの複数のプロパティを関数内で使用する場合、都度user.nameやuser.ageと記述する代わりに、冒頭で分割してしまうことで繰り返しの記述を避けることができます。

type User = {
  name: string;
  age: number;
};

const greetUser = function ({ name, age }: User): string {
  return `こんにちは、${name}さん (${age}歳)`;
};

このように、引数の段階で必要なプロパティのみを明示的に取り出すことで、関数内部の可読性が大きく向上しますね(functionよりアローの方が主流ですね😅)

可変長引数とスプレッド構文

引数の数が定まらない関数を定義するためにrest引数(...args)を利用することができます。

const printTags = (title: string, ...tags: string[]): void => {
  console.log(`記事: ${title}`);
  console.log("タグ:", tags.join(", "));
};

printTags("TypeScript入門", "typescript", "js", "programming");

上記の例では、記事タイトルに加えて、任意の数のタグを渡すことができます。
また、rest引数はスプレッド構文と組み合わせて使用されることが多く、これは関数に渡すデータの数が実行時にしか確定しないような場面で、柔軟に対応できるからです。

関数の型注釈が必要かどうかについて

型注釈があるとないのとの違いはコンパイルエラーの出力の違いです。
例えばnumber[]という型注釈をつけていて、戻り値が何もない場合のエラーメッセージは、「返り値の型注釈がvoidでもanyでもない関数は値を返す必要があります」というエラーメッセージで理解が容易でありかつ、関数実行時に呼ばれるけど型注釈をつけないと関数実行時にコンパイルエラーが走らない、
なら全ての関数に型注釈をつけるかというとそうでもなく、つける必要がない関数もあります。
変数宣言時に型注釈がある場合かコールバック関数です。
ここでは理解深めるためにコールバック関数を例にしてみます。

const items = [1, 2, 3];
items.map((x) => x * 2);

mapをvscodeでcommand+クリックをすると

map<U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[];

というように、入力の型Tから任意の型Uへの変換処理を可能にするための型宣言であり、ジェネリクスを用いることで柔軟な変換処理を型安全に記述できるようになっていますね。
コールバック関数自体をcommand+クリックして中身を見に行くことがあまりなかったので次から取り入れたい要素でした👍

参考

https://gihyo.jp/book/2022/978-4-297-12747-3

まとめ

  • void 関数でも早期にreturnできる
  • 分割代入で関数の引数をシンプルにできる
  • rest 引数やスプレッド構文を使って柔軟な関数設計ができる
  • 型注釈があることでエラー検出が明確になる
  • コールバック関数の定義の深掘り

Discussion