カテゴリ: TypeScript 更新日: 2026/04/02

TypeScriptでtry/catchを使わない!Result型で安全なエラー処理を実現する方法

TypeScriptでtry/catchを使わずに型で安全性を担保する手法(Result型)
TypeScriptでtry/catchを使わずに型で安全性を担保する手法(Result型)

先生と生徒の会話形式で理解しよう

生徒

「TypeScriptのプログラムでエラーが起きたとき、try/catchで囲むのが面倒だと感じます。もっと安全で分かりやすい方法はありませんか?」

先生

「その悩みは多くのプログラマーが抱えるものです。TypeScriptの型機能を使えば、try/catchを使わずに安全にエラーを扱うResult型という手法がありますよ。」

生徒

「Result型を使うと、具体的に何が嬉しいんですか?」

先生

「エラーを例外として隠すのではなく、戻り値として扱うことで、プログラムの流れが劇的に分かりやすくなるんです。一緒に学んでいきましょう!」

1. プログラミングにおける例外処理とtry/catchの基本

1. プログラミングにおける例外処理とtry/catchの基本
1. プログラミングにおける例外処理とtry/catchの基本

プログラミングをしていると、どうしても予測できない問題が発生します。例えば、インターネットからデータをもらうときに通信が切れたり、存在しないファイルを開こうとしたりすることです。これらを専門用語で例外と呼びます。従来のプログラムでは、この例外が起きると処理が強制終了してしまうため、try/catchという仕組みを使って処理をキャッチし、止まらないようにしてきました。

try/catchは、成功するか失敗するかわからないコードを「try(試す)」ブロックに入れ、もし問題があれば「catch(捕まえる)」ブロックで対応するという流れです。しかし、これがコードのあちこちに散らばると、どこで何が起きるのか把握しづらくなってしまうという欠点があります。

2. なぜtry/catchを使わない設計が推奨されるのか

2. なぜtry/catchを使わない設計が推奨されるのか
2. なぜtry/catchを使わない設計が推奨されるのか

なぜtry/catchを避けるべきだと言われるのでしょうか。最大の理由は「処理の流れが見えなくなること」にあります。関数が失敗したとき、どのエラーがどこで投げられるのか、TypeScriptの型システムだけでは追いかけるのが難しいためです。開発者が「この関数はエラーを投げるかもしれない」と覚えておかなければならず、見落としが発生しやすいのです。

そこで登場するのがResult型という考え方です。Result型は、「成功したときは値を持つ」と「失敗したときはエラーの理由を持つ」という二つの状態を型として明確に定義します。これにより、エラーもデータの一部として扱うことができ、プログラマーは強制的にエラーの発生を考慮するように設計できるようになります。

3. TypeScriptでResult型を自作する方法

3. TypeScriptでResult型を自作する方法
3. TypeScriptでResult型を自作する方法

TypeScriptには標準でResult型が用意されているわけではありませんが、自分で簡単に作ることができます。型定義と呼ばれる機能を使って、成功と失敗の状態を定義します。まずはシンプルな実装例を見てみましょう。


type Success<T> = { success: true; data: T };
type Failure = { success: false; error: string };
type Result<T> = Success<T> | Failure;

function divide(a: number, b: number): Result<number> {
    if (b === 0) {
        return { success: false, error: "ゼロで割ることはできません" };
    }
    return { success: true, data: a / b };
}

このコードでは、Success型Failure型を定義し、それらを合体させたResult型を作成しました。ジェネリクスという機能(型をあとから決める仕組み)を使い、成功したときに返すデータの型を自由に設定できるようにしています。このように定義することで、関数の結果がどちらの形になるのかをTypeScriptが理解できるようになります。

4. 型による安全性を担保するとはどういうことか

4. 型による安全性を担保するとはどういうことか
4. 型による安全性を担保するとはどういうことか

TypeScriptの強力な機能である型ガードを使うことで、実行結果の安全性を担保します。型ガードとは、条件分岐を使って、変数の型を特定する仕組みです。下記のコードを見てください。


const result = divide(10, 0);

if (result.success) {
    console.log("計算結果:", result.data);
} else {
    console.error("エラーが発生しました:", result.error);
}

この例では、if文を使ってresult.successがtrueかどうかをチェックしています。もしtrueであれば、TypeScriptは「あ、これは成功したデータだからdataプロパティがあるんだな」と判断してくれます。逆にelseブロックでは「これはエラーデータだからerrorプロパティがあるはずだ」と判断し、安全に値へアクセスできるようになります。これが、実行前に型によって安全性が保証されるという仕組みです。

5. 実際の現場でのResult型活用メリット

5. 実際の現場でのResult型活用メリット
5. 実際の現場でのResult型活用メリット

実際の開発現場では、多くの関数や通信処理が組み合わさります。Result型を使うと、エラーの処理が関数を呼ぶ側で強制されるため、バグの混入を劇的に減らすことができます。特に大規模なアプリケーションでは、何百もの関数を組み合わせて使うため、エラーを型として扱うメリットは計り知れません。

例えば、データベースにアクセスしたり、APIという外部サービスと連携したりするとき、成功と失敗の型が明示されていると、開発者はエラー処理を書き忘れることがありません。これは保守性が高いコードを作るための重要な技術です。最初は少し書き方が増えるように感じるかもしれませんが、将来的な修正のしやすさを考えると非常に合理的です。

6. 複雑な条件を扱うための実践コード

6. 複雑な条件を扱うための実践コード
6. 複雑な条件を扱うための実践コード

最後に、少し発展的な例として、処理を連続して実行する場合の例を見てみましょう。Result型は連続する処理でも威力を発揮します。


function getUserId(name: string): Result<number> {
    if (name === "admin") return { success: true, data: 1 };
    return { success: false, error: "ユーザーが存在しません" };
}

const userResult = getUserId("guest");

if (!userResult.success) {
    console.log("処理を中止します:", userResult.error);
} else {
    const userId = userResult.data;
    console.log("ユーザーID:", userId);
}

このように、一つの関数だけでなく、プログラム全体でResult型を統一して使うことで、エラー処理のルールが整います。結果として、デバッグ(プログラムの誤りを見つけて修正する作業)が非常に楽になります。例外を投げ飛ばしてどこで捕まえるか悩む必要はなく、その場で結果を確認して次に進むという、明確で健全なプログラムが書けるようになるのです。

関連記事:
カテゴリの一覧へ
新着記事
New1
TypeScript
TypeScriptでtry/catchを使わない!Result型で安全なエラー処理を実現する方法
New2
JavaScript
JavaScriptのループのデバッグ方法とよくあるエラー解説!初心者でもわかる原因と対処法
New3
JavaScript
JavaScriptのループ処理を短く書く書き方のコツ!初心者でもわかる繰り返しコードの簡略化テクニック
New4
JavaScript
JavaScriptの非同期処理とは?仕組みと必要性をやさしく解説【初心者向け完全ガイド】
人気記事
No.1
Java&Spring記事人気No1
JavaScript
JavaScriptのインストール方法まとめ!Windows・Mac・Linux別にステップ解説
No.2
Java&Spring記事人気No2
JavaScript
JavaScriptプログラムの実行方法まとめ!ブラウザ・Node.js・コンソールの使い方
No.3
Java&Spring記事人気No3
JavaScript
JavaScriptのtoStringとString関数の違いを初心者向けに解説
No.4
Java&Spring記事人気No4
TypeScript
TypeScriptのnever型を使ったエラーハンドリング!例外処理を極める安全なコードの書き方
No.5
Java&Spring記事人気No5
TypeScript
TypeScriptのAxiosエラーハンドリングを初心者向けに解説!型安全な例外処理の方法
No.6
Java&Spring記事人気No6
JavaScript
JavaScriptのonclick・onchangeなどの基本イベントを理解しよう
No.7
Java&Spring記事人気No7
TypeScript
TypeScriptで最初に覚えたい基本構文まとめ
No.8
Java&Spring記事人気No8
TypeScript
TypeScriptでエラー処理を共通関数化して効率的に開発しよう!初心者向け例外処理ガイド