diff --git a/types/_utils.d.ts b/types/_utils.d.ts index 6da4403440..6c155e5774 100644 --- a/types/_utils.d.ts +++ b/types/_utils.d.ts @@ -10,3 +10,5 @@ export type NullableParams = { export type WithAdditionalParams> = T & Record + +export type Awaitable = T | PromiseLike diff --git a/types/index.d.ts b/types/index.d.ts index f3e34bc63d..77e5f1d7b8 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -4,10 +4,10 @@ import { ConnectionOptions } from "typeorm" import { Adapter } from "./adapters" -import { JWTEncodeParams, JWTDecodeParams, JWTOptions, JWT } from "./jwt" +import { JWTOptions, JWT } from "./jwt" import { AppProvider, Providers } from "./providers" import { NextApiRequest, NextApiResponse, NextApiHandler } from "./_next" -import { NonNullParams, WithAdditionalParams } from "./_utils" +import { Awaitable, NonNullParams, WithAdditionalParams } from "./_utils" export interface NextAuthOptions { providers: Providers @@ -62,30 +62,34 @@ export interface AppOptions providers: AppProvider[] } -export interface CallbacksOptions { - signIn?: - | (() => true) - | (( - user: User, - account: Record, - profile: Record - ) => Promise) - redirect?: (url: string, baseUrl: string) => Promise - session?: - | ((session: Session) => WithAdditionalParams) - | (( - session: Session, - userOrToken: User | JWT - ) => Promise>) - jwt?: - | ((token: JWT) => WithAdditionalParams) - | (( - token: JWT, - user: User, - account: Record, - profile: Record, - isNewUser: boolean - ) => Promise>) +export interface Account extends Record { + accessToken: string + idToken?: string + refreshToken?: string + access_token: string + expires_in?: number | null + refresh_token?: string + id_token?: string + id: string + provider: string + type: string +} +export interface Profile extends Record {} + +export interface CallbacksOptions< + P extends Record = Profile, + A extends Record = Account +> { + signIn?(user: User, account: A, profile: P): Awaitable + redirect?(url: string, baseUrl: string): Awaitable + session?(session: Session, userOrToken: JWT | User): Awaitable + jwt?( + token: JWT, + user?: User, + account?: A, + profile?: P, + isNewUser?: boolean + ): Awaitable } export interface CookieOption { diff --git a/types/tests/server.test.ts b/types/tests/server.test.ts index c9877ab24f..fdab54e04a 100644 --- a/types/tests/server.test.ts +++ b/types/tests/server.test.ts @@ -165,10 +165,10 @@ const allConfig = { }, async jwt( token: JWTType.JWT, - user: NextAuthTypes.User, - account: Record, - profile: Record, - isNewUser: boolean + user?: NextAuthTypes.User, + account?: Record, + profile?: Record, + isNewUser?: boolean ) { return token }, diff --git a/www/docs/getting-started/typescript.md b/www/docs/getting-started/typescript.md index acefde43c4..445652be1e 100644 --- a/www/docs/getting-started/typescript.md +++ b/www/docs/getting-started/typescript.md @@ -1,22 +1,77 @@ --- id: typescript -title: TypeScript Support +title: TypeScript --- -Currently, NextAuth.js relies on the community to provide TypeScript types. You can download it from [DefinitelyTyped](https://www.npmjs.com/package/@types/next-auth). +NextAuth.js comes with its own types, so you can safely use it in your TypeScript projects. Even if you don't use TypeScript, IDEs like VSCode will pick this up, to provide you with a better developer experience. While you are typing, you will get suggestions of what certain objects are, and sometimes also links to documentation, and examples. -Add it to your project with: +:::note + The types at [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped) under the name of `@types/next-auth` are now deprecated, and not maintained anymore. +::: -```sh -npm i -D @types/next-auth +*** +## Module Augmentaion + +`next-auth` comes with certain types/interfaces, that are shared across submodules. Good examples are `Session` and `JWT`. Ideally, you should only need to create these types at a single place, and TS should pick them up in every location where they are referenced. Luckily, this is exactly what Module Agumentation can do for us. Define your shared interfaces in a single location, and get type-safety across your application, when you use `next-auth` (or one of its submodules). + +1. Let's look at `Session`: + +```ts title="pages/api/[...nextauth].ts" +import NextAuth from "next-auth" + +export default NextAuth({ + callbacks: { + session(session, token) { + return session // The type here should match the one returned in `useSession()` + } + } +}) ``` -or +```ts title="pages/index.ts" +import { useSession } from "next-auth/client" -```sh -yarn add -D @types/next-auth +export default function IndexPage() { + // `session` should match `callbacks.session()` in `NextAuth()` + const [session] = useSession() + + return ( + // Your component + ) +} ``` -You can find an initial Pull Request at [next-auth#516](https://github.com/nextauthjs/next-auth/pull/516) adding TypeScript. At the time of this writing, it looks like we would like to go from a complete migration to a more relaxed, incremental rewrite. +To extend/augment this type, create a `types/next-auth.d.ts` file in your project: + +```ts title="types/next-auth.d.ts" +import NextAuth from "next-auth" + +declare module "next-auth" { + interface Session { + user: { + /** The user's postal address. */ + address: string + } + } +} +``` + +Make sure that the `types` folder is added to [`typeRoots`](https://www.typescriptlang.org/tsconfig/#typeRoots) in your project's `tsconfig.json` file. + +2. Check out `JWT` also: + +```ts title="types/next-auth.d.ts" +declare module "next-auth/jwt" { + interface JWT { + /** OpenID ID Token */ + idToken?: string + } +} +``` + +Note that this time we declared `JWT` inside `next-auth/jwt`, as this is its default location. + + +## Contributing -Feel free to open a Pull Request, if you would like to contribute! \ No newline at end of file +Contributions of any kind are always welcome, especially for TypeScript. Please keep in mind that we are a small team working on this project in our free time. We will try our best to give support, but if you think you have a solution for a problem, please open a PR!