Next.js と TypeScript で、配列の型注釈を理解する

TwitterFacebookHatena

TL;DR

このページでは、Next.js と TypeScript を用いた配列の型注釈の実装方法について解説しますね。一言でいうと配列の型注釈とは、配列が持つ要素の型を明示的に指定することです。

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

「配列の型注釈」の基本

「配列の型注釈」とは、TypeScript で配列とその要素の型を明示的に宣言する方法のことを指します。これにより、配列内の要素が期待する型を保証でき、コードの安全性と可読性を向上させることができます。

TypeScript では、配列の型注釈は主に二つの書き方があります。一つ目は、「型[]」という形式です。これは、「この配列は特定の型の要素だけを含む」という意味になります。以下に具体的な例を見てみましょう。

let numbers: number[] = [1, 2, 3]
let names: string[] = ['Alice', 'Bob', 'Charlie']

この例では、「numbers」は数値の配列で、「names」は文字列の配列として型注釈されています。つまり、「numbers」には数値しか含めることができず、「names」には文字列しか含めることができないという制約が付けられています。

二つ目は、「Array<型>」という形式です。これも「型[]」と同じく、特定の型の要素だけを含む配列を表します。この形式は特に複雑な型やユニオン型(複数の型のいずれか)を扱う場合に便利です。

let numbers: Array<number> = [1, 2, 3]
let names: Array<string> = ['Alice', 'Bob', 'Charlie']
let mixed: Array<number | string> = [1, 'Alice']

ここでは、「numbers」、「names」は先程と同様に型注釈されています。「mixed」はユニオン型を使用しており、数値か文字列のどちらかの型の要素を含む配列として型注釈されています。

複数の型を持つ配列の型注釈

配列が複数の型の要素を含む場合、それぞれの型を | で繋げて表現します。

let array: (string | number)[] // 配列が文字列か数字を含むことを示す型注釈
array = ['apple', 1, 'banana', 2]

配列の中のオブジェクトの型注釈

配列がオブジェクトを要素として持つ場合、それぞれのオブジェクトについても型注釈を行うことができます。

type Fruit = {
  name: string
  sweetness: number
}

let fruits: Fruit[] // 配列がFruitオブジェクトを含むことを示す型注釈
fruits = [
  { name: 'apple', sweetness: 8 },
  { name: 'banana', sweetness: 10 },
]

ネストした配列の型注釈

配列がさらに配列を要素として持つ、ネストした配列の場合、[] を繰り返すことで表現します。

let array: string[][] // 配列が文字列の配列を含むことを示す型注釈
array = [
  ['apple', 'banana'],
  ['mango', 'peach'],
]

読み取り専用の配列の型注釈

配列が読み取り専用(つまり、配列の要素が変更されることを防ぐ)であるべき場合、readonly キーワードを使用します。

let array: readonly string[] // 配列が読み取り専用であることを示す型注釈
array = ['apple', 'banana']
// array[0] = 'pear'; // これはエラーを引き起こします、配列は読み取り専用です。

任意の型を含む配列の型注釈

配列が任意の型の要素を含む可能性がある場合(つまり、全ての種類の値が配列に入ることが許可されている)、any 型を使用します。

let array: any[] // 配列が任意の型の要素を含むことを示す型注釈
array = ['apple', 1, true, { name: 'banana' }, ['mango']]

しかし、any 型は TypeScript の型安全性を弱めるため、特定の場合以外では使用を避けることが推奨されます。

同じ形状を持つオブジェクトの配列の型注釈

配列が同じ形状を持つオブジェクトのみを含むことを示すためには、インラインでオブジェクトの型を定義することも可能です。

let users: { id: number; name: string }[] // 同じ形状を持つオブジェクトの配列の型注釈
users = [
  { id: 1, name: 'Alice' },
  { id: 2, name: 'Bob' },
  // { id: 3, age: 25 }, // これはエラーを引き起こします、オブジェクトは 'name' プロパティを持つ必要があります
]

複数の特定の型を含む配列の型注釈

配列が特定の複数の型を持つ場合、その型を組み合わせることも可能です。これは、Union Types(共用体)と呼ばれる機能を使用します。

let array: (number | string)[] // 配列が数字または文字列の要素を含むことを示す型注釈
array = [1, 'apple', 2, 'banana']
// array = [1, 'apple', true]; // これはエラーを引き起こします、真偽値は許可されていません

Tuple(タプル)の型注釈

配列の各要素が異なる型を持つ場合、Tuple(タプル)という機能を使用します。

let pair: [string, number] // タプルの型注釈、配列の最初の要素は文字列で、次の要素は数字であることを示す
pair = ['apple', 1]
// pair = [1, 'apple']; // これはエラーを引き起こします、要素の型が一致しません

型エイリアスを使用した配列の型注釈

コードの可読性を高めるために、型エイリアスを使用してカスタムの配列型を作成することも可能です。

type User = { id: number; name: string }
let users: User[] // 型エイリアスを使用した配列の型注釈
users = [
  { id: 1, name: 'Alice' },
  { id: 2, name: 'Bob' },
]

これらの例は、TypeScript の配列の型注釈の応用的な使用例を示しています。より複雑な型の定義や注釈を行うためには、これらの基本的な概念を組み合わせることがしばしばあります。

Next.js で、配列の型注釈を実装

それでは、Next.js で配列の型注釈をどのように使用するか見ていきましょう。ここでは、ユーザーのリストを表示するシンプルなコンポーネントを作成します。

まず、ユーザーを表す型を定義します。この例では、ユーザーは名前と年齢を持つとします。

// types.ts
type User = {
  name: string
  age: number
}

次に、ユーザーのリストを受け取り、それを表示するコンポーネントを作成します。

// components/UserList.tsx
import { User } from '../types'

type Props = {
  users: User[]
}

const UserList = ({ users }: Props) => {
  return (
    <ul>
      {users.map((user, index) => (
        <li key={index}>{`${user.name} (${user.age} years old)`}</li>
      ))}
    </ul>
  )
}

export default UserList

この UserList コンポーネントは、プロパティとして User 型の配列 users を受け取ります。そして、受け取った users を map 関数でループして、リストとして表示します。各ユーザーの名前と年齢を表示する形式にしています。

ここで注目すべき点は、users の型注釈 User[] です。これにより、このコンポーネントは User 型の要素からなる配列を受け取ることを明示しています。

以上が、Next.js と TypeScript を用いて配列の型注釈を使用する一例です。型注釈を正しく使用することで、期待するデータ構造を明確にし、エラーを早期に検出できます。

Next.js と TypeScript で、配列の型注釈を理解する