第6章 冒頭のミスをTypeScriptで防いでみよう
それでは、今回の記事の冒頭で示した「起こりがちなミス」をTypeScriptで解決しましょう。
その1 プロパティ名ミス
typeでUserという型を作り、saveUser関数の引数userに型を付けます。型はuser: Userのように書きます。
type User = {
name: string;
email: string;
};
// ユーザー情報の保存
function saveUser(user: User) {
console.log("Name:", user.name);
console.log("Email:", user.email);
}
// 呼び出し側
saveUser({
neme: "佐藤太郎", // タイプミス
email: "tarou@example.com"
});
VSCodeで、この型を加えた段階でnemeに赤線が現れてエラーが検出されます。
次に、npx tscで型チェックをしてみましょう。
npx tsc main.ts
この方法では、変換したJavaScriptが出力されます。型チェックだけをおこないたいときは、--noEmitを付けます。
npx tsc main.ts --noEmit
いずれの場合でも、次のようにエラーが表示されます。ミスはどこだろうと、血眼になってコードを確認する必要がなくなります。
main.ts:14:5 - error TS2353: Object literal may only specify known properties, and 'neme' does not exist in type 'User'.
14 neme: "佐藤太郎", // タイプミス
~~~~
Found 1 error in main.ts:14
その2 型ミス
Configという型を作り、プロパティの型を確認するようにしましょう。setup関数の引数configに型を付けます。型はconfig: Configのように書きます。
type Config = {
retry: number;
timeout: number;
};
// 設定
function setup(config: Config) {
console.log("Config:", config);
}
// 呼び出し側
setup({
retry: "3", // numberなのに、stringで渡した
timeout: 5000
});
VSCodeで、この型を加えた段階でsetupの引数に書いたretryに赤線が現れてエラーが検出されます。
次に、npx tscで型チェックをしてみましょう。エラーがあるのは分かっているので、JavaScriptのファイルは出力せずに、型チェックだけをおこないます。
npx tsc main.ts --noEmit
次のようにエラーが表示されます。起こりうるエラーを未然に防ぐことができます。
main.ts:13:5 - error TS2322: Type 'string' is not assignable to type 'number'.
13 retry: "3", // numberなのに、stringで渡した
~~~~~
main.ts:2:3
2 retry: number;
~~~~~
The expected type comes from property 'retry' which is declared here on type 'Config'
Found 1 error in main.ts:13
その3 プロパティを間違えて扱う
今度は、少し難しいケースです。TypeScriptの型の書き方には、「あってもなくても構わないプロパティ」を指定する方法があります。age?: numberのように?を付ける記法です。まずは、この方法で型を指定します。
type UserProfile = {
name: string;
age?: number; // Optional
};
// プロフィールの表示
function displayProfile(user: UserProfile) {
console.log("Name:", user.name);
console.log("Age:", user.age.toFixed(0));
}
// 呼び出し側
displayProfile({
name: "太郎" // ageは未設定
});
このコードを書くと、VSCodeでdisplayProfile関数のuser.ageの部分に赤線が引かれます。
マウスカーソルを重ねてポップアップすると'user.age' is possibly 'undefined'.というメッセージが表示されます。ageプロパティの値がundefinedになる可能性があるというエラーです。
このコードを、tsconfig.jsonを作っていない状態で、そのままtscで型チェックします。この場合、実はエラーが出ません。
npx tsc main.ts --noEmit
tscでの型チェックは、デフォルトの状態では、今回のケースのエラーを検出しません。検出するためには、strictNullChecksをtrueにする必要があります。
設定を変更するには、tsconfig.jsonを作成して設定を変更するか、実行時引数に値を追加します。今回は後者の方法を利用します。
npx tsc main.ts --noEmit --strictNullChecks true
この方法で実行すると、次のようにエラーが出力されます。
main.ts:9:25 - error TS18048: 'user.age' is possibly 'undefined'.
9 console.log("Age:", user.age.toFixed(0));
~~~~~~~~
Found 1 error in main.ts:9
エラーが検出されたので、コードを修正しましょう。user.age.toFixed(0)の部分をuser.age?.toFixed(0)に変更します。
.を?.に変更したことで、ageがundefinedの場合はtoFixedを実行しないようになりました。
type UserProfile = {
name: string;
age?: number; // Optional
};
// プロフィールの表示
function displayProfile(user: UserProfile) {
console.log("Name:", user.name);
console.log("Age:", user.age?.toFixed(0));
}
// 呼び出し側
displayProfile({
name: "太郎" // ageは未設定
});
このコードを出力して、Node.jsで実行してみましょう。出力するコードはes2024準拠にします。
npx tsc main.ts --strictNullChecks true --target es2024 node main.js
Name: 太郎 Age: undefined
エラーが出ずに実行できました。TypeScriptでは、このようにしてエラーを防げます。
まとめと次回予告
今回は、TypeScriptに軽く入門してみました。次回からはさらに踏み込んで、TypeScriptの仕様に触れていきます。
