TypeScriptを3ヶ月使って感じたメリット・デメリット【JavaScriptとの比較】
TypeScriptを本格的に使い始めて3ヶ月が経った。
「型があると安心」「JavaScriptより保守しやすい」という話はよく聞く。でも実際に使い始めると「なんで型エラーが出るんだ」「anyにしてとりあえず動かそう」という場面も少なくない。
良いことも悪いことも含めて、実務で感じたリアルをまとめる。
TypeScriptとは(簡単におさらい)
TypeScriptはJavaScriptに静的型システムを追加したプログラミング言語。Microsoftが開発し、最終的にはJavaScriptにトランスパイル(変換)される。
// JavaScript
function greet(name) {
return "Hello, " + name;
}
// TypeScript(型を追加)
function greet(name: string): string {
return "Hello, " + name;
}
name に数値や undefined を渡すと、TypeScriptならコンパイル時にエラーになる。JavaScriptなら実行するまでわからない。
使い始めたきっかけ
チームで開発しているプロジェクトのフロントエンドがReact + TypeScriptに移行することになり、半強制的に学ぶことになった。
それまではJavaScript(+ESLint)で書いていて、「型なんていらないのでは」と思っていた側の人間だった。
使ってみて感じたメリット
① バグが減った(特に型まわりの凡ミス)
一番実感したのはこれだ。
例えばAPIのレスポンスを処理するコードで、undefined かもしれないプロパティに直接アクセスしてしまうミスをTypeScriptが事前に検出してくれる。
type User = {
id: number;
name: string;
email?: string; // オプショナル
};
function showEmail(user: User) {
// TypeScriptがエラーを出す
console.log(user.email.toUpperCase()); // ❌ emailはundefinedかもしれない
// これが正しい書き方
console.log(user.email?.toUpperCase()); // ✅
}
JavaScriptなら実行時に TypeError: Cannot read property 'toUpperCase' of undefined が出るまで気づかない。TypeScriptなら書いている時点でエラーになる。
② コードの補完が強力になる
VSCodeとTypeScriptを組み合わせると、オブジェクトのプロパティ補完が正確になる。
型が定義されているオブジェクトなら、ドットを打った瞬間に「使えるプロパティの一覧」が出てくる。複雑なAPIのレスポンス型を定義しておけば、打ち間違いや存在しないプロパティへのアクセスをエディタが事前に防いでくれる。
③ リファクタリングが怖くなくなった
関数の引数の型を変えたとき、その関数を呼び出している全箇所でTypeScriptがエラーを出してくれる。
JavaScriptだとリファクタリング後に「動くかどうかテストしてみないとわからない」だったが、TypeScriptなら「型エラーがなければ大きな問題はない」という自信が持てる。
④ チームでのコード理解が速くなる
型定義がドキュメントの役割を果たす。
// この関数が何を受け取って何を返すか、型を見ればわかる
async function createPost(
title: string,
content: string,
authorId: number
): Promise<Post> {
// ...
}
コメントがなくても、型を見れば関数の使い方がわかる。新しいメンバーがコードを読むときの障壁が下がった。
使ってみて感じたデメリット・しんどかったこと
① 学習コストが思ったより高かった
「JavaScriptがわかればTypeScriptはすぐ使える」と聞いていたが、実際はそう単純ではなかった。
特に最初にしんどかったもの:
- ジェネリクス(
<T>の意味と使い方) - ユニオン型・インターセクション型(
A | B・A & B) - 型ガード(
typeof・instanceof・カスタム型ガード) asキャストの正しい使い方と罠
使い始めの1〜2週間は型エラーに苦しんで、集中力の半分を型と戦うことに使っていた印象だった。
② anyの誘惑に負けがち
型エラーが解決できないとき、any 型で一時的に逃げたくなる。
// anyで型チェックを無効化してしまう例
const data: any = response.data; // ❌ TSの恩恵を台無しにする
any を使うとTypeScriptの恩恵がなくなる。でも締め切りが迫っているとき、any にして「後で直す」が溜まっていくのが現実だ。
③ 外部ライブラリの型定義が面倒なことがある
TypeScriptの型定義がない外部ライブラリを使う場合、自分で型定義ファイル(.d.ts)を書く必要がある場合がある。
多くのライブラリは @types/ライブラリ名 で型定義が提供されているが、古いライブラリや小規模なライブラリは型定義が存在しないケースもある。
④ 設定(tsconfig.json)が最初わかりにくい
tsconfig.json の設定項目が多く、最初はどこを変えれば何が変わるかわからなかった。
{
"compilerOptions": {
"strict": true, // 厳格モード(推奨)
"target": "ES2020",
"module": "ESNext",
"moduleResolution": "bundler",
"noUncheckedIndexedAccess": true // 配列アクセスの安全性を上げる
}
}
とりあえず "strict": true で始めておけば、多くの問題は防げる。
TypeScriptを使うべきか?
| 状況 | 判断 |
|---|---|
| チーム開発・中〜大規模プロジェクト | 使うべき(型がドキュメントになる) |
| 長期運用するプロジェクト | 使うべき(リファクタリングが安全) |
| 個人の小規模ツール・スクリプト | JSで十分(オーバーエンジニアリング) |
| プロトタイプ・PoC | JSで始めて後からTS化でも良い |
3ヶ月後の正直な感想
最初の1ヶ月は「面倒だな」という気持ちが強かった。
でも2〜3ヶ月続けていると、型があることが当たり前になってきて、逆に「型なしで書くのが不安」という感覚に変わってきた。
特にリファクタリングの安心感とチームでのコード共有のしやすさは、使い続けることで実感できる良さだと思っている。
「面倒でも続ける価値はあった」というのが3ヶ月後の正直な評価だ。
まとめ
| 項目 | 評価 |
|---|---|
| バグの予防効果 | ◎ |
| 補完・開発体験 | ◎ |
| リファクタリングの安全性 | ◎ |
| 学習コスト | △(JSより高い) |
| 小規模スクリプトへの適性 | △(オーバーキル) |
TypeScriptは「使い始めるのが大変だが、使い続けるほど恩恵が増える」ツールだと思っている。チームで使うなら導入を検討する価値は十分ある。