導入
今日の話題はNuxt3のserver middlewareで追加したevent contextにTypeScriptの型を付けたいという内容です。
(Nuxt3のバージョンは3.6で確認)
※ 私が株式会社愛宕 Advent Calendar 2023に書く記事は主に社内向けに共有しておきたいけど勉強会をするまでもないちょっとしたTipsにしたいと思います。
Nuxt3ではサーバーサイドの実装でミドルウェアを作成しリクエストごとに共通的に呼び出される処理を記述することができます。
さらに、このミドルウェアの内部でevent contextに何らかの値を代入すると各APIで利用できるようになって便利です。
例えば、認証済かどうかチェックしてセッションオブジェクトを構築しcontextに紐づけておくなどの使い方が一般的でしょう。
export default defineEventHandler(async (event) => {
const sessionId = getCookie(event, "cookie-name")
// 取得したデータを使って何かの構築をしたり判定をしたり
// ...中略...
event.context.hoge = new Hoge(sessionId) // 各APIで共通的に使えるように代入しておく
})
ここで、event.contextのインターフェースにはhogeはないですが、extends Record<string, any>で宣言されているため一応hogeというプロパティは使用できます。
ただし、型がanyになってしまい、各APIで使用するときに不便です。
正しくHoge型を付けるにはどうすればいいんでしょうか?
解決
TypeScriptでは既存の型を拡張することができます。event.contextはh3モジュールのH3EventContextというインターフェースなので次のようにすれば型を付けることができます。
declare module 'h3' {
// 普通にここにインターフェースを書けばマージしてくれる
interface H3EventContext {
hoge: Hoge
}
}
同様に、サーバーサイドのプラグインでnitroAppにデータを埋め込んで各APIでuseNitroApp()を呼び出して再利用することもできます。ただし、こちらはextends Record<string, any>ではないのでこういう使い方は非推奨なのかもしれません。
export default defineNitroPlugin((nitroApp) => {
// ...省略...
nitroApp.dependencies.push(hogeClient)
})
nitroAppはnitropackモジュールのNitroAppというインターフェースなので次のようにすれば型を付けることができます。
declare module 'nitropack' {
// 普通にここにインターフェースを書けばマージしてくれる
interface NitroApp {
dependencies: Dependency[]
}
}