Rami Chasygov
Rami Chasygov

Reputation: 2784

Merge your types with existing, Typescript

I have a interface (below), what I want to achieve is change property req, add to it my custom type, per se req: { session: { userId?: string } }, is it possible to merge my type and library Request type?

interface MyContext {
  req: Request;
  res: Response;
}

Upvotes: 2

Views: 1140

Answers (2)

Karol Majewski
Karol Majewski

Reputation: 25850

When two interfaces share the same name, subsequent property declarations must have the same type. This means it's easy to add another property using declaration merging, but it's not easy to override it.

When it's an intersection

If you want to simply add another property to Request, you can use declaration merging.

declare global {
    interface Request {
        session: {
            userId?: string
        }
    }
}

When it's a union

In order to override the definitions provided by a third-party library, you need to create your own version for them and include it in your project. There is a downside — they will not be merged together. You need to re-create (or copy-paste) every type definition delivered by my-module you care about.

my-module.d.ts

declare module 'my-module' {
  interface MyContext {
    req: Request | { session: { userId?: string } };
    res: Response;
  }
}

However, the fact you need to override third-party type definitions almost always indicates one of two things:

  • you are not using the library the way it was intended to be used, or
  • the type definitions are incorrect and should be fixed upstream.

Upvotes: 4

Robbie Milejczak
Robbie Milejczak

Reputation: 5780

You can use extends:

interface MyContext extends Request {
  //what ever props you want to add
}

Now MyContext has all the properties assigned to the Request type, as well as whatever you define.

If for some reason you only need specific parts of the Request type or you do not want to use interfaces, I'd suggest checking out the utility-types library, specifically the Assign, Pick, and Omit types it provides.

You could say:

type MyType = { ...whatever props you need to add}
type MyRequest = Assign<Request, MyType>

and now MyRequest has the props you'd like to add.

You could also pick types from, or remove types from Request. Suppose Request has a foo prop that you want to remove:

type MyRequest = Omit<Request, 'foo'>

or maybe you only want an imaginary prop called bar:

type JustBarFromRequest = Pick<Request, 'bar'>

and you can Assign those new types as you see fit.

If you just need to build on an existing interface then definitely stick with extends. If you need to alter and compose props and types then I highly recommend reading about utility-types

Upvotes: 1

Related Questions