TL;DR
このページでは、Rest パラメータの実装方法について解説しますね。一言でいうと Rest パラメータとは、JavaScript や TypeScript で関数に可変長の引数を渡すための特別な構文です。では、実際に使ってみましょう。
開発環境 | バージョン |
---|---|
Next.js | 13.4.4 |
TypeScript | 5.0.4 |
Emotion | 11.11.0 |
React | 18.2.0 |
Rest パラメータ(残余引数)とは?
Rest パラメータは、JavaScript と TypeScript の関数で、引数の数が不確定な場合に使用します。Rest パラメータを使うと、複数の引数を配列としてまとめることができます。
Rest パラメータとは、関数に任意の数の引数を渡すことを可能にする JavaScript と TypeScript の特性を指します。
この特性は "残余引数" とも呼ばれ、3 つのドット(...)を引数名の前に付けることで利用できます。これにより、関数は可変数の引数を配列として受け取ることができます。
const sampleFunction = (...args: number[]) => {
/* ... */
}
この sampleFunction
は、引数の数がいくつであっても処理できます。ここで、args
は配列として扱われ、関数内部で配列のメソッドを利用することができます。
また、Rest パラメータ(残余引数)は引数リストの最後にしか置くことができず、一つの関数内では一度しか使うことができません。これらは、Rest パラメータを使用する際の重要なルールです。
以下は、基本的な Rest パラメータの使用方法です。
const sum = (...numbers: number[]): number => {
return numbers.reduce((prev, current) => prev + current, 0)
}
console.log(sum(1, 2, 3, 4)) // 10
上記の sum
関数は、...numbers: number[]
という形で Rest パラメータを定義しています。この ...numbers
は、関数 sum
に渡された任意の数の引数をnumbers
という配列にまとめてくれます。この関数は、1
, 2
, 3
, 4
といった任意の数の引数を受け取り、それらをすべて足し合わせた結果を返します。
Rest パラメータは関数の引数リストの最後に書く
Rest パラメータは関数の引数リストの最後にある必要があります。
Rest パラメータは、その位置から関数の最後までのすべての引数を配列にまとめる役割を持っています。そのため、Rest パラメータの後に他の引数を置くことはできません。以下のようなコードは無効です。
// これは無効です。
const invalidFunction = (...args: number[], anotherArg: string) => {
// do something
}
これを TypeScript で実行しようとすると、コンパイラは次のようなエラーメッセージを出力します:
A rest parameter must be last in a parameter list.
これは、「Rest パラメータはパラメータリストの最後でなければならない」という意味です。
Rest パラメータについて理解する際に注意すべき点
Rest パラメータについて理解する際に注意すべき点としては以下の 2 つがあります。
- Rest パラメータは引数リストの最後にしか配置できません。
- Rest パラメータは一つの関数内で一度だけしか使用できません。
分かりやすい例を一つ挙げましょう。以下は、与えられた全ての数字を合計する関数を Rest パラメータを使って実装したものです。
type NumericArray = number[]
const sum = (...numbers: NumericArray) => {
let total = 0
for (const num of numbers) {
total += num
}
return total
}
console.log(sum(1, 2, 3, 4)) // 10を出力します。
この例では、sum
関数は任意の数の引数を取ることができます。これらの引数はすべて numbers
配列に格納され、それを用いて総和を求めています。
なお、Rest パラメータは TypeScript の特性であり、JavaScript や他の多くのプログラミング言語でも使われている特性です。これにより関数が可変長の引数を柔軟に扱うことができ、コードの再利用性と可読性を向上させることができます。
Next.js で、Rest パラメータを実装
それでは Next.js と TypeScript を使って、Rest パラメータの実装例を見てみましょう。今回は、複数の CSS スタイルを結合する mergeStyles
関数を作成します。
components/mergeStyles.tsx
:
import { css, SerializedStyles } from '@emotion/react'
type Styles = SerializedStyles | SerializedStyles[]
const mergeStyles = (...styles: Styles[]): SerializedStyles => {
return css(styles.flat())
}
export default mergeStyles
この mergeStyles
関数では、...styles: Styles[]
という形で Rest パラメータを受け取ります。これにより、引数として複数のスタイルオブジェクトを受け取ることができます。そして、styles.flat()
により、ネストされた配列もフラットにすることができます。
Emotion での利用例
それでは、作成した mergeStyles
関数を Emotion で利用してみましょう。Next.js のコンポーネントで、複数のスタイルを結合して適用する例を示します。
components/MyComponent.tsx
:
/** @jsxImportSource @emotion/react */
import { css } from '@emotion/react'
import mergeStyles from './mergeStyles'
type Props = {
isActive: boolean
}
const MyComponent = ({ isActive }: Props) => {
const activeStyle = css`
color: blue;
`
const baseStyle = css`
font-size: 16px;
`
return <div css={mergeStyles(baseStyle, isActive && activeStyle)}>Hello, World!</div>
}
export default MyComponent
このコンポーネントでは、mergeStyles(baseStyle, isActive && activeStyle)
という形で、mergeStyles
関数を利用しています。isActive
がtrue
の場合、activeStyle
が適用され、false
の場合は適用されません。これにより、動的にスタイルを結合することができます。
API ルートの動的パラメータ
Next.js では、API ルートでも Rest パラメータを活用することができます。これにより、動的な URL パラメータを扱うことが可能になります。以下に、その例を示します。
pages/api/user/[...username].ts
:
import type { NextApiRequest, NextApiResponse } from 'next'
type Params = {
username: string[]
}
type Data = {
username: string
}
const handler = (req: NextApiRequest, res: NextApiResponse<Data>) => {
const { username } = req.query as Params
res.status(200).json({ username: username.join('/') })
}
export default handler
この API ルートでは、[...username]
という形で Rest パラメータを定義しています。この形式を使うことで、/api/user/john/doe
のような URL が全てこの API ルートにマッチします。そして、username
パラメータは['john', 'doe']
という配列として取得できます。