📔

[Next] API Routesのreq, resの型について

2021/07/19に公開1

前提

Next.jsでAPI Routesを使用する際、以下のようなコードを書くと思います。

const handler = (req, res) => { 
  res.status(200).json({ ... })
}

export default handler

このreq, resに型をつける方法がわからなかったので調べました。

Next.jsの公式ページを確認する

公式ページのAPI Routesの部分にreq, resについての情報がありました。
https://nextjs.org/docs/api-routes/introduction#use-cases

req: An instance of http.IncomingMessage, plus some pre-built middlewares
res: An instance of http.ServerResponse, plus some helper functions

reqはhttp.IncomingMessage、resはhttp.ServerResponseのようです。
そのため下記のようなコードを書いてみました。

import { IncomingMessage, ServerResponse } from 'http'

const handler = (req: IncomingMessage, res: ServerResponse) => {
  res.status(200).json({ ... })
}

export default handler

しかしres.statusの部分でエラーが発生してしまいました。

import { IncomingMessage, ServerResponse } from 'http'

const handler = (req: IncomingMessage, res: ServerResponse) => {
    // Property 'status' does not exist on type 'ServerResponse'.ts(2339)
    res.status(200).json({ ... })
}

export default handler

ServerResponseにはstatusという型は存在しないそうです。

Next.js公式のTypeScriptページを見る

次にNext.js公式でTSのページを見ると、API Routesに関して言及があり、req, resの型についても言及されていました。
https://nextjs.org/docs/basic-features/typescript#api-routes

import type { NextApiRequest, NextApiResponse } from 'next'

export default (req: NextApiRequest, res: NextApiResponse) => {
  res.status(200).json({ name: 'John Doe' })
}

どうやらreq, resは既に定義済みらしく、nextモジュールからNextApiRequest, NextApiResponseとして参照できるようです。

まとめ

ということで、下記コードを書いて解決できました。

import type { NextApiRequest, NextApiResponse } from 'next'

export const handler = async (req: NextApiRequest, res: NextApiResponse) => {
  const URL = `${process.env.NEXT_PUBLIC_RSS_TO_JSON_URL}${process.env.NEXT_PUBLIC_ZENN_URL}&api_key=${process.env.RSS_TO_JSON_API_KEY}&count=9`
  const { data } = await axios.get(URL)

  res.status(200).json({ articles: data })
}

※ちなみにimport typeとすることで、その型のみをimportすることができるようです。

Discussion

convers39convers39

ありがとうございます。参考になりました。

補足だけですが、handler関数に直接つければ引数のタイプも推測できます:

import type { NextApiHandler } from 'next'

const handler: NextApiHandler = async (req, res) => {}

export default handler