簡単な個人開発のログインで、NextAuthを使用しました。
やりたいこと
sessionオブジェクトが用意されているのですが、デフォルトだと以下の値が参照できるようになっています。
session.user.name session.user.email session.user.image session.expires
私のプロダクトでは、user.idを参照できるようにしたいです。
session.user.id
sessionオブジェクトにuser.idを追加する
[...nextauth].ts ファイルのoptions: callbacksに以下のように書き、要素を追加します。
// [...nextauth].ts import NextAuth from 'next-auth' - 中略 - const options = { - 中略 - callbacks: { async session(session, user) { session.user.id = user.sub return Promise.resolve(session) }, } }
型をつける
今のままだと参照した際に型エラーになってしまうので、型をつけます。
types/next-auth.d.ts を作成し、以下のように書きます。
declare module "next-auth" { interface Session { user: { id: string | null } } }
エラーがなくなりました。
何をしたのか
ライブラリの中身を見てみると、デフォルトだとDefaultSession型が参照されます。
export interface DefaultSession extends Record<string, unknown> { user?: { name?: string | null email?: string | null image?: string | null } expires?: string } export interface Session extends Record<string, unknown>, DefaultSession {}
今回は、独自に定義したSession型を参照するようにしました。
declare module "next-auth" { interface Session { user: { id: string | null } } }
ハマったこと
デフォルトでは、Session型はDefaultSessionをextendsしています。
てっきり↓こんな感じで拡張されていると思っていたのですが、上記の型定義だとuser.idしか参照できません。
export interface DefaultSession { user?: { name?: string | null email?: string | null image?: string | null } expires?: string } interface Session { user?: { id?: string | null } } interface NewSession extends DefaultSession, Session {} const session: NewSession = { user: { name: 'a', email: 'b', id: 'a' } } // 参照できると思っていたけど、 session.user.idだけうまく参照できない。 session.user.id session.user.name session.user.email session.user.image session.expires
NewSessionには以下のようなエラーが出ていました。
Interface 'NewSession' cannot simultaneously extend types 'DefaultSession' and 'Session'. Named property 'user' of types 'DefaultSession' and 'Session' are not identical.
ref: github.com
同じ名前のプロパティは継承できないんですね。変な勘違いをしていました。
以上です!