Diego
Diego

Reputation: 73

Extend a type from a node package

How can I extend the types from a node package without modifying the @types files?

import { Session, useSession } from 'next-auth/client'

// I AM TRYING TO EXTEND THE Session TYPE

export default function Component() {
  // useSession() returns type-> useSession(): [Session, boolean]
  const [session]: [<ENTER EXTENDED TYPE HERE>, boolean] = useSession()
  ...
}

Types from @types/next-auth

type Session = SessionBase & GenericObject;

interface SessionBase {
    user: User;
    accessToken?: string;
    expires: string;
}

interface User {
    name?: string | null;
    email?: string | null;
    image?: string | null;
}

The result should be a type like this:

type NewSession = NewSessionBase & Session;

interface NewSessionBase {
    user: {
      name?: string | null;
      email?: string | null;
      image?: string | null;
      myCustomData?: {
        uid: string | null;
    }
};
    accessToken?: string;
    expires: string;
}

This would fix the error: "TS2741", "Property is missing in type but required in type"

Upvotes: 1

Views: 235

Answers (1)

You can just overwrite user property of Session type.

type GenericObject = {}

type Session = SessionBase & GenericObject;

interface SessionBase {
  user: User;
  accessToken?: string;
  expires: string;
}

interface User {
  name?: string | null;
  email?: string | null;
  image?: string | null;
}

type NewSession = NewSessionBase & Session;


type NewUser = {
  name?: string | null;
  email?: string | null;
  image?: string | null;
  myCustomData?: {
    uid: string | null;
  }
}

interface NewSessionBase {
  user: NewUser;
  accessToken?: string;
  expires: string;
}

// The main part of answer
type ExtendedSession = Session & {user: NewUser};

This is more exotic way to replace one type of property with another. You can use it if you have more complicated replacing logic

type Replace<Obj, Property extends keyof Obj, NewType> = {
  [P in keyof Obj]: P extends Property ? NewType : Obj[P]
}

type Foo = Replace<{ expires: string }, 'expires', number> // { expires: number }

Upvotes: 1

Related Questions