🕌
TypeScriptで関数を書くときに気をつけている事
TypeScriptで関数を書く際に、気をつけていることを記載しました。
BMIを計算する処理を例にして説明いたします。
object
形式にする
引数を引数をobject
形式にする事で名前付き引数に近い形式になり、順不同になります。引数の順番に意味が無い関数でも、使用時にどの順番で引数を渡すか迷う事がありません。
const calculateBMI = (p: { height: number; weight: number }) => {
// BMIの計算処理
};
calculateBMI({ height: 170, weight: 60 });
calculateBMI({ weight: 60, height: 170 });
以下は、引数がobject
ではありません。この関数だけ見ると特に違和感は無いと思います。しかし、上記に比べると情報量が減ります。特にheight
, weight
ともにnumber
なので使用時に順番に迷うことがあります。
const calculateBMI = (height: number, weight: number) => {
// BMIの計算処理
};
calculateBMI(170, 60);
適切なブロックコメントを記載する
以下のようなブロックコメントを記載します。メソッドを使用時にエディタにヒントが表示され開発の補助になります。
/**
* [BMI](https://ja.wikipedia.org/wiki/%E3%83%9C%E3%83%87%E3%82%A3%E3%83%9E%E3%82%B9%E6%8C%87%E6%95%B0)
*/
const calculateBMI = (p: {
/**
* 身長
*/
height: number;
/**
* 体重
*/
weight: number;
}) => {
// BMIの計算処理
};
calculateBMI({ height: 170, weight: 60 });
calculateBMI({ weight: 60, height: 170 });
-
身長
,体重
は、和訳のコメントなので適切なコメントではありません。 - TS Playgroundでも確認可能です。
拡張性を担保する
引数をobject
形式にするに付随するメリットですが、引数を追加する場合オプショナルにする事が容易になります。
/**
* [BMI](https://ja.wikipedia.org/wiki/%E3%83%9C%E3%83%87%E3%82%A3%E3%83%9E%E3%82%B9%E6%8C%87%E6%95%B0)
* `height`, `weight`以外の引数がある場合、制度の高い結果が取得できます。
*/
const calculateBMI = (p: {
gender?: 'male' | 'female';
height: number;
weight: number;
age?: number;
}) => {
// 複雑なBMIの計算処理
};
// 引数が順不同
calculateBMI({ height: 170, weight: 60, age: 20, gender: 'male' });
// 新たに追加した引数は、オプショナルな為互換性を担保しやすい
calculateBMI({ height: 170, weight: 60 });
- TS Playgroundでも確認可能です。
テストを書く
正しい実装である事を検証する事は重要です。また、特殊なケースなどはコメントを追記すれば、コードリーディングの手助けになります。
今回のようなシンプルなメソッドであれば、test.each
が適切だと思います。
/**
* [BMI](https://ja.wikipedia.org/wiki/%E3%83%9C%E3%83%87%E3%82%A3%E3%83%9E%E3%82%B9%E6%8C%87%E6%95%B0)
* `height`, `weight`以外の引数がある場合、制度の高い結果が取得できます。
*/
export const calculateBMI = (p: {
gender?: 'male' | 'female';
height: number;
weight: number;
age?: number;
}) => {
// 複雑なBMIの計算処理
return 20; // 検証用のコードなのでハードコーディングです。
};
import { calculateBMI } from './service';
import { describe, expect, test } from 'vitest';
describe('calculateBMI', () => {
type TestData = {
param: Parameters<typeof calculateBMI>[0];
expected: ReturnType<typeof calculateBMI>;
};
const testData: TestData[] = [
{
param: {
height: 170,
weight: 60,
},
expected: 20,
},
{
param: {
height: 170,
weight: 60,
// genderがmaleの場合は、XXXを考慮してBMIがZZZになる
gender: 'male',
},
expected: 20,
},
{
param: {
height: 170,
weight: 60,
gender: 'male',
// ageが20未満の場合は、XXXを考慮してBMIがZZZになる
age: 18,
},
expected: 20,
},
];
test.each(testData)('入力値と結果 %o', ({ param, expected }) => {
expect(calculateBMI(param)).toEqual(expected);
});
});
ちょっと株式会社(chot-inc.com)のエンジニアブログです。 フロントエンドエンジニア募集中! カジュアル面接申し込みはこちらから chot-inc.com/recruit/iuj62owig
Discussion