Next.js と TypeScript で、try...catch 構文を理解する

TwitterFacebookHatena

TL;DR

このページでは、try...catch 構文の実装方法について解説しますね。一言でいうと、try...catch 構文とは、エラーの発生を前提としたコードの書き方で、エラーが発生したときにその場でキャッチして処理を続行できる素晴らしい考え方です。

開発環境 バージョン
Next.js 13.4.4
TypeScript 5.0.4
Emotion 11.11.0
React 18.2.0

try...catch 構文とは?

まず、基本的な考え方から解説しますね。エラーハンドリングはプログラミングにおいて重要な要素で、それを行う一つの方法が try...catch 構文です。プログラムがエラーをスローする可能性がある部分を try ブロックに包み、エラーが発生した際に実行される処理を catch ブロックに書きます。

それでは、基本的な使い方を見てみましょう。

try {
  // エラーが投げられる可能性があるコード
} catch (error) {
  // ここでエラー処理を行う
}

ここで error はエラーオブジェクトを受け取る変数で、エラーが発生した際にはその詳細が格納されます。

例えば、不適切な操作でエラーが発生する可能性のある配列へのアクセスを try ブロックに書くことができます。

try {
  const array = [1, 2, 3]
  console.log(array[5]) // 存在しないインデックスへのアクセス
} catch (error) {
  console.error('エラーが発生しました:', error)
}

このコードでは、存在しない配列のインデックスへアクセスしようとしています。しかし、JavaScript ではこれはエラーを発生させません。それではエラーが発生するコードを書いてみましょう。

try {
  throw new Error('意図的にエラーを発生させます') // エラーを発生させる
} catch (error) {
  console.error('エラーが発生しました:', error)
}

この例では、throw ステートメントを使用して人為的にエラーを発生させています。このエラーは catch ブロックによって捕捉され、エラーメッセージがコンソールに表示されます。

Next.js で、try...catch 構文を実装

それでは、Next.js で try...catch 構文をどのように使うのかを見てみましょう。ここでは、API からデータを取得するときに、エラーハンドリングを行います。

ファイル名: pages/index.tsx

import { useEffect, useState } from 'react'

type Data = {
  /* Data definition */
}

const HomePage = () => {
  const [data, setData] = useState<Data | null>(null)

  useEffect(() => {
    const fetchData = async () => {
      try {
        const res = await fetch('/api/data')
        if (!res.ok) {
          throw new Error('サーバーエラーが発生しました')
        }
        const data: Data = await res.json()
        setData(data)
      } catch (error) {
        console.error('エラーが発生しました:', error)
      }
    }
    fetchData()
  }, [])

  return <div>{/* Data display */}</div>
}

export default HomePage

このコードでは、fetchData 関数内で try ブロックを使用しています。ここで、非同期処理を行う fetch 関数を呼び出しています。この関数は Promise を返し、その Promise が reject されたとき、または fetch 関数内でエラーが投げられたときに catch ブロックが実行されます。

catch ブロック内では、エラーメッセージをコンソールに表示しています。これにより、API の呼び出しに失敗した原因を特定しやすくなります。

このコードの一部では、API から返されたレスポンスのステータスを確認し、それが ok プロパティ(レスポンスが成功した場合に true)でない場合には新しいエラーをスローしています。これにより、サーバーからエラーレスポンスが返された場合にもエラーハンドリングが可能となります。

try...catch 構文を深掘り

さらに深く掘り下げて、更に高度なテクニックを見てみましょう。それはエラーの型を自分で定義し、それに基づいてエラーハンドリングを行う方法です。

まず、自分で定義したエラー型を紹介します。

class MyError extends Error {
  constructor(message?: string) {
    super(message)
    this.name = 'MyError'
  }
}

MyErrorは、JavaScript の組み込みオブジェクトであるErrorを継承したクラスです。これにより、標準的なエラーオブジェクトと同じ性質を持つ独自のエラー型を作成することができます。

それでは、これを使ってエラーハンドリングを行ってみましょう。

try {
  // エラーを発生させる
  throw new MyError('これは自分で定義したエラーです')
} catch (error) {
  if (error instanceof MyError) {
    console.error('MyErrorが発生しました:', error)
  } else {
    console.error('未知のエラーが発生しました:', error)
  }
}

この例では、throw ステートメントで MyError を投げています。catch ブロック内では、エラーが MyError のインスタンスかどうかを instanceof 演算子で判断しています。これにより、エラーの型に基づいた条件付きのエラーハンドリングが可能となります。

以上が try...catch 構文の基本的な使い方と応用例です。これらのテクニックを使うことで、エラーが発生したときのプログラムの挙動をより詳細に制御することができます。エラーハンドリングは、プログラムが安定して動作することを保証する重要な部分であるため、是非この知識を活かしてください。

Next.js と TypeScript で、try...catch 構文を理解する