1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

実行してみないとエラーが分からないから卒業しよう。TypeScriptで安全なコードを書くための実践ガイド

1
Posted at

はじめに:JavaScriptのこんな悩み、ありませんか?

JavaScriptでコードを書いていて、こんな経験はないでしょうか?

  • ブラウザで実行してみたら「Cannot read property 'name' of undefined」で真っ赤に
  • 関数に渡す引数の型を勘違いしていて、数値と文字列が混ざって謎の結果に
  • リファクタリングしたら、関係ないと思っていた箇所で不具合が発生
  • 他人(または過去の自分)が書いた関数の引数に、何を渡せばいいのか分からない

こうした問題の多くは、「実行するまで型が分からない」 というJavaScriptの性質に起因しています。そして、これを根本から解決してくれるのが TypeScript です。

この記事では、TypeScriptを導入するメリットと、実際にエラーを防ぐための安全なコードの書き方を、具体的なコード例とともに解説します。読み終わる頃には、「なぜ多くの現場でTypeScriptが採用されているのか」がはっきりと分かるはずです。


TypeScriptとは?「静的型付け」がもたらす安心感

TypeScriptは、Microsoftが開発したJavaScriptのスーパーセット(上位互換)言語です。最大の特徴は、変数や関数の引数・戻り値に「型」を指定できることにあります。

// JavaScript:型情報がない
function add(a, b) {
  return a + b;
}
add(1, "2"); // "12"(文字列連結になってしまう!)

// TypeScript:型を明示
function add(a: number, b: number): number {
  return a + b;
}
add(1, "2"); // ❌ コンパイル時にエラー!実行前に気づける

このように、バグを実行前(コーディング中)に検出できるのがTypeScriptの真骨頂です。


TypeScriptを導入する4つの大きなメリット

1. バグを実行前に発見できる

型チェックによって、typoや型の取り違えといった凡ミスを、コードを書いている最中に検出できます。テストや本番環境で初めて気づく、という事態を大幅に減らせます。

2. エディタの補完が劇的に賢くなる

VSCodeなどのエディタが、変数や関数の型情報を元に正確な補完候補を出してくれます。オブジェクトのプロパティ名を思い出す必要も、ドキュメントを開く必要もありません。

3. リファクタリングが怖くなくなる

関数の引数を変更したり、プロパティ名をリネームしたりすると、影響範囲がすべてコンパイルエラーとして可視化されます。「変更したけど、どこかで壊れていないか不安」という状態から解放されます。

4. コード自体がドキュメントになる

型定義を見れば、「この関数は何を受け取り、何を返すのか」が一目で分かります。チーム開発においても、コミュニケーションコストを大きく下げてくれます。


実践編:エラーを防ぐ安全なコードの書き方

ここからは、実際にTypeScriptを使って安全なコードを書くための、具体的なテクニックを紹介します。

テクニック1:基本の型を正しく使う

まずはプリミティブ型をしっかり指定するところから。

const userName: string = "Taro";
const age: number = 30;
const isActive: boolean = true;
const tags: string[] = ["typescript", "javascript"];

「型注釈は書かなくても推論してくれる」場面も多いですが、関数の引数と戻り値には必ず型を書くことをおすすめします。

テクニック2:interfacetypeでオブジェクトの形を定義する

複雑なオブジェクトを扱うときは、型を先に定義しておくと安全です。

interface User {
  id: number;
  name: string;
  email: string;
  role: "admin" | "member" | "guest"; // リテラル型で選択肢を制限
}

const user: User = {
  id: 1,
  name: "Hanako",
  email: "hanako@example.com",
  role: "admin",
};

// role: "superuser" と書くとエラーになる → 想定外の値が入らない

roleのようにリテラル型のユニオンを使うと、指定できる値そのものを制限できます。これはバグ防止に非常に効果的です。

テクニック3:undefinednullを明示的に扱う

多くのバグは「値があると思ったらなかった」ことから生まれます。TypeScriptでは、strictNullChecksを有効にすることで、undefinednullの可能性を型で表現できます。

function findUser(id: number): User | undefined {
  // 見つからない可能性がある
  return users.find((u) => u.id === id);
}

const user = findUser(1);
console.log(user.name); // ❌ エラー:userはundefinedの可能性がある

// ✅ 正しい書き方
if (user) {
  console.log(user.name); // OK:ここではuserはUser型
}

// または、オプショナルチェイニングで
console.log(user?.name);

「値があるかどうか」を型システムが強制的にチェックさせてくれるため、Cannot read property of undefinedエラーが激減します。

テクニック4:ジェネリクスで再利用可能な型安全コードを書く

同じロジックを異なる型で使いたい場合、ジェネリクスを使うと型安全性を保ったまま再利用できます。

// 配列の最初の要素を返す関数
function first<T>(array: T[]): T | undefined {
  return array[0];
}

const num = first([1, 2, 3]);        // number | undefined
const str = first(["a", "b", "c"]);  // string | undefined

Tという「型の変数」を使うことで、どんな型の配列にも対応しつつ、戻り値の型も正しく推論されます。

テクニック5:anyは最終手段。まずはunknownを検討する

「面倒だからanyを使う」は避けたいところ。anyを使うとTypeScriptの恩恵をすべて失います。型が不明な場合は、まずunknownを検討しましょう。

// ❌ 避けたい書き方
function parse(data: any) {
  return data.name.toUpperCase(); // 実行時エラーの可能性
}

// ✅ 型ガードで安全に扱う
function parse(data: unknown): string {
  if (
    typeof data === "object" &&
    data !== null &&
    "name" in data &&
    typeof (data as { name: unknown }).name === "string"
  ) {
    return (data as { name: string }).name.toUpperCase();
  }
  throw new Error("Invalid data");
}

unknownは「なんでも入るけど、使う前に型チェックを強制する」型です。外部APIのレスポンスなど、型が不確定なデータを扱うときに重宝します。

テクニック6:strictモードを有効にする

tsconfig.jsonstrict: trueを設定すると、TypeScriptの型チェックが最も厳しくなります。

{
  "compilerOptions": {
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "noUncheckedIndexedAccess": true
  }
}

新規プロジェクトでは必ずstrict: trueから始めるのが鉄則です。後から緩めることは簡単ですが、厳しくするのは大変です。


まとめ

TypeScriptで安全なコードを書くためのポイントを、あらためて振り返っておきましょう。

  • 型を明示することで、実行前にバグを検出できる
  • interface / typeでオブジェクトの構造を厳密に定義する
  • リテラル型のユニオンで、取りうる値を制限する
  • undefined / nullは型で明示し、必ずチェックする
  • ジェネリクスで、型安全な再利用可能コードを書く
  • anyではなくunknownを使い、strictモードを有効にする

最初は「型を書くのが面倒」と感じるかもしれません。ですが、慣れてくると 「型がないと逆に不安」 と感じるようになるはずです。型はあなたのコードを守ってくれる、頼れる相棒です。


さらに手を動かしながら学びたい方へ

この記事ではTypeScriptの基本的な考え方と、安全なコードを書くためのテクニックを紹介しました。ただ、こうした知識は「読んで理解する」だけではなかなか身につかず、実際にエラーメッセージと向き合いながら試行錯誤する経験が何よりも大切です。

そんな学習スタイルを求めている方への1つの選択肢として、【手を動かして学ぶ】TypeScript完全入門 - エラーで学ぶ安全なコードの書き方 という講座があります。

タイトルにもある通り、エラーで学ぶというアプローチが特徴で、実際に起こりがちな型エラーを1つずつ体験しながら、その原因と解決方法を身につけていく構成になっています。「なぜこのエラーが出るのか」「どう修正するのが正解なのか」を手を動かしながら理解できるので、独学だと曖昧なまま進んでしまいがちな部分をしっかり固めたい方に向いているかもしれません。

もちろん、公式ドキュメントを読み込む、既存プロジェクトにTypeScriptを段階的に導入してみる、など学び方は人それぞれです。この記事や上記の講座が、あなたのTypeScript学習の助けとなれば嬉しく思います。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?