Next.js と TypeScript で学ぶ、find() メソッド

TwitterFacebookHatena

TL;DR

このページでは、JavaScript の find() メソッドの実装方法について解説しますね。一言でいうと find() メソッドとは、配列内の要素を検索し、最初に見つけた要素を返す関数です。

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

find() メソッドとは?

JavaScript の find() メソッドは、配列内の各要素に対して指定した関数を実行し、その関数が真(true)を返す最初の要素を返します。これは、例えばある条件を満たす要素を配列から探す際に非常に便利です。

以下に基本的なソースコードの例を示します。ここでは find() メソッドを使って、配列から最初の奇数を見つける例を考えてみます。

const numbers = [2, 4, 5, 6, 8]
const firstOdd = numbers.find((num) => num % 2 !== 0)

console.log(firstOdd) // -> 5

このコードでは、配列 numbers から find() メソッドを使って最初の奇数を探しています。find() メソッドには、検索条件を指定する関数(この場合は num => num % 2 !== 0)を引数として渡します。この関数は、配列の各要素に対して実行され、真を返す最初の要素(この場合は 5)が find() メソッドの戻り値となります。

特定のユーザーを見つける例

それでは、Next.js と TypeScript を用いた具体的なコードを見てみましょう。ユーザーの情報が格納された配列から、特定のユーザーを見つける例を考えます。

以下の User 型と users 配列を考えます。

// models/user.ts

type User = {
  id: number
  name: string
}

const users: User[] = [
  { id: 1, name: 'Alice' },
  { id: 2, name: 'Bob' },
  { id: 3, name: 'Charlie' },
]

この users 配列から、特定の id を持つユーザーを見つける関数 findUserById() を実装します。

// utils/findUserById.ts

import { User, users } from '../models/user'

const findUserById = (id: number): User | undefined => {
  return users.find((user) => user.id === id)
}

この findUserById() 関数では、引数としてユーザー ID を受け取り、find() メソッドを使ってその ID を持つユーザーを users 配列から探します。find() メソッドに渡す関数 user => user.id === id では、各ユーザーの id プロパティが引数の id と等しいかどうかを確認します。該当するユーザーが見つかった場合はそのユーザーを、見つからなかった場合は undefined を返します。

特定の条件を満たす要素を見つける

それでは、もう少し複雑な例を見てみましょう。複数のフィールドを持つ配列から、特定の条件を満たす要素を見つける例を考えます。

まず、以下のような商品の配列を考えます。

// models/item.ts

type Item = {
  id: number
  name: string
  category: string
}

const items: Item[] = [
  { id: 1, name: 'T-shirt', category: 'clothing' },
  { id: 2, name: 'Jeans', category: 'clothing' },
  { id: 3, name: 'Sneakers', category: 'shoes' },
]

この items 配列から、特定のカテゴリーの最初の商品を見つける関数 findFirstItemByCategory() を実装します。

// utils/findFirstItemByCategory.ts

import { Item, items } from '../models/item'

const findFirstItemByCategory = (category: string): Item | undefined => {
  return items.find((item) => item.category === category)
}

この findFirstItemByCategory() 関数では、引数としてカテゴリーを受け取り、find() メソッドを使ってそのカテゴリーの最初の商品を items 配列から探します。find() メソッドに渡す関数 item => item.category === category では、各商品の category プロパティが引数の category と等しいかどうかを確認します。該当する商品が見つかった場合はその商品を、見つからなかった場合は undefined を返します。

アロー関数と分割代入の使用

アロー関数と分割代入を活用して、先ほどの findUserById 関数をより見やすく書くことができます。具体的には、find メソッドの引数として渡す関数内で分割代入を使用します。

// utils/findUserById.ts

import { User, users } from '../models/user'

const findUserById = (id: number): User | undefined => {
  return users.find(({ id: userId }) => userId === id)
}

この書き方では、配列の各要素(ここでは user オブジェクト)を分割代入して id プロパティを userId という名前で直接取り出しています。これにより、コードがより簡潔になり、user.id と書くよりも読みやすくなります。

要素が複数ある場合

find メソッドは配列の要素が条件を満たすものが複数ある場合でも、最初に見つかった要素だけを返します。もし条件を満たす全ての要素を取得したい場合は、filter メソッドを使用します。

以下の例では、特定のカテゴリーに属する全ての商品を見つける関数 findAllItemsByCategory を実装しています。

// utils/findAllItemsByCategory.ts

import { Item, items } from '../models/item'

const findAllItemsByCategory = (category: string): Item[] => {
  return items.filter((item) => item.category === category)
}

この関数では、引数としてカテゴリーを受け取り、filter メソッドを使ってそのカテゴリーの全ての商品を items 配列から探します。filter メソッドに渡す関数 item => item.category === category では、各商品の category プロパティが引数の category と等しいかどうかを確認します。該当する商品が見つかった場合はその商品を配列として、見つからなかった場合は空の配列を返します。

他の引数について

find メソッドに渡す関数は、引数として配列の各要素だけでなく、その要素のインデックスや元の配列も受け取ることができます。以下の例では、findWithIndex 関数を実装して、配列の要素とそのインデックスを同時に取得します。

// utils/findWithIndex.ts

import { User, users } from '../models/user'

const findWithIndex = (id: number): [User | undefined, number] => {
  let foundUser: User | undefined
  let foundIndex: number = -1

  users.find((user, index) => {
    if (user.id === id) {
      foundUser = user
      foundIndex = index
      return true
    }
    return false
  })

  return [foundUser, foundIndex]
}

この関数では、find メソッドのコールバック関数が要素 user とそのインデックス index の両方を引数として受け取ります。見つけた要素とそのインデックスを保持するための変数 foundUserfoundIndex を用意して、条件に一致した要素が見つかった時点でその値を更新しています。このようにして、見つけた要素とそのインデックスを一緒に返すことができます。

Next.js と TypeScript で学ぶ、find() メソッド