In TypeScript, How do I go about adding a property to an object type in an Interface?

Viewed 81

I am trying to understand how to merge declare an interface, but instead of adding a field to the interface itself, I wish to add a property to the object literal type.

I have a type defined in a library as follows:

interface DefaultSession {
    user?: {
      name?: string | null;
      email?: string | null;
      image?: string | null;
    };
    expires: ISODateString;
}

I know that if I wanted to add a field to this interface without changing the name, I could simply reopen and declare:

interface DefaultSession {
    role?: string
}

I have been studying the Typescript Handbook, but I can't find a way to merge declare role as a property under user to yield a type as follows:

interface DefaultSession {
    user?: {
        name?: string | null;
        email?: string | null;
        image?: string | null;
        role?: string | null;
    };
    expires: ISODateString;
}
2 Answers

What you are looking for is intersection type:

https://www.typescriptlang.org/docs/handbook/unions-and-intersections.html

Just declare your custom type like following:

interface DefaultSession {
  user?: {
    name?: string | null;
    email?: string | null;
    image?: string | null;
  };
  expires: ISODateString;
}

type CustomDefaultSession = DefaultSession & {
  user?: {
    role?: string | null;
  }
}

Then you can use it like it is or implement it for your class. Besides if you want the same name for your custom type then just refer library type using alias.

If you have a callback inside library you can override argument type like the following:

// Callback defined inside the library.
type LibraryCallback = (defaultSession: DefaultSession) => void;

// Function inside the library which accepts callback.
function libraryFunction(libraryCallback: LibraryCallback): void
{
    // Do stuff...
}

// Application code which calls library function and changes callback argument type.
libraryFunction((customDefaultSession: CustomDefaultSession) =>
{
    const role = customDefaultSession.user.role;
});

Just do the following:

export interface Foo {
    user?: {
      name?: string | null;
      email?: string | null;
      image?: string | null;
    };
    expires: Date;
}


export interface Bar extends Foo {
  user?: Foo['user'] & {
    role?: string
  }
} 

First, extend the Bar form Foo and assign the user just like above with & sign. & merges two object types. Thus you get:

enter image description here

Related