Next.js と TypeScript で、オプショナルプロパティ(?)を使う

TwitterFacebookHatena

TL;DR

このページでは、"オプショナルプロパティ"の実装方法について解説しますね。一言でいうとオプショナルプロパティとは、プロパティが存在しなくてもエラーにならないようにするための記述法です。

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

オプショナルプロパティとは?

オプショナルプロパティは TypeScript の便利な機能の一つで、これを利用すると特定のプロパティがオブジェクトに存在しなくてもエラーを出さないようにできます。

?は「オプショナルマーカー」または「オプショナルプロパティ」と呼ばれます。プロパティ名の後ろに?をつけることで、そのプロパティがオプショナル(つまり、存在してもしなくても良い)であることを示します。

具体的には、以下のような形で使います。

type User = {
  name: string
  age?: number
}

このコードではUserという型を定義しています。nameは必ず存在するプロパティで、その型はstringとなっています。一方で、agenumber型のプロパティであると同時に、末尾に?がついていることで、これがオプショナルプロパティであることを示しています。

言い換えれば、プロパティは undefined でもよい、ということです。この機能は、オブジェクトのプロパティが必ずしもすべて存在しない場合や、オプショナルな設定がある場合などに非常に便利です。

このUser型を使ったオブジェクトを作るとき、ageプロパティが存在しなくてもエラーは出ません。

const user1: User = {
  name: 'John',
}

const user2: User = {
  name: 'Jane',
  age: 25,
}

user1ageが未指定でも問題ありません。しかし、nameを省略した場合やageに文字列を入れようとした場合には、TypeScript は型エラーを出します。

Next.js で、オプショナルプロパティを実装

では、Next.js のプロジェクトでオプショナルプロパティを実際に使ってみましょう。ここでは、ユーザーの情報を表示するコンポーネントを作ります。その際に、ユーザーの年齢は必ずしも存在しないとします。

ファイル名:components/UserProfile.tsx

import { css } from '@emotion/react'

type UserProps = {
  name: string
  age?: number
}

const UserProfile = ({ name, age }: UserProps) => {
  return (
    <div css={containerStyle}>
      <div>名前: {name}</div>
      {age && <div>年齢: {age}</div>}
    </div>
  )
}

const containerStyle = css`
  width: 200px;
  border: 1px solid #333;
  padding: 20px;
  margin-bottom: 20px;
`

export default UserProfile

このUserProfileコンポーネントでは、UserPropsという型でnameageを定義しています。nameは必須のプロパティで、ageはオプショナルプロパティとなっています。

コンポーネントの中で、ageが存在すればその値を表示し、存在しなければ何も表示しないという条件分岐を行っています。これにより、ageが未定義でもエラーが起こることはありません。

高等なオプショナルプロパティの実装

さらに高度な例として、オプショナルプロパティがネストしたオブジェクトに対する取り扱いを見てみましょう。

type Address = {
  city?: string
  zipCode?: string
}

type User = {
  name: string
  age?: number
  address?: Address
}

const UserProfile = ({ name, age, address }: User) => {
  return (
    <div css={containerStyle}>
      <div>名前: {name}</div>
      {age && <div>年齢: {age}</div>}
      {address?.city && <div>都市: {address.city}</div>}
      {address?.zipCode && <div>郵便番号: {address.zipCode}</div>}
    </div>
  )
}

ここでは、Addressという型を新しく定義して、その型をUseraddressプロパティの型として使っています。そして、そのaddressもまたオプショナルプロパティとなっています。

コンポーネント内では、addressが存在する場合だけ、そのプロパティcityzipCodeを表示します。ここでは Optional Chaining(?.)を用いて、addressundefinedまたはnullの場合にエラーを出さないようにしています。

これらのオプショナルプロパティを理解して使うことで、存在しないかもしれないプロパティを安全に扱うことができます。

Next.js と TypeScript で、オプショナルプロパティ(?)を使う