Search code examples
typescriptoverriding

Can I override any type property in Typescript?


I'm trying to attach my custom types into Express's Request/Response interface.

But some properties are of type any, so I'm having really hard to override it.

ex:

// @types/expres-server-static-core
interface Request {
  cookies?: any;
}

// my.ts
import type {Request} from 'express';

type MyCookies = {
  'apple'?: string;
  'banana'?: string;
}

interface MyRequest extends Request {
  cookies: MyCookies
}

// my-usecase.ts
const request: MyRequest = /* */; // MyRequest | Request
request.cookies; // still has any type because MyCookies | any will be any type

I know anytype is the top type of typescript so customized cookiesproperty will be ignored.
So I'm using like:

const myRequest: MyCookies = req.cookies;
// or
const myRequest = req.cookies as MyCookies;

It can solve this problem but I don't want to declare MyCookies constants; req.cookies = MyCookies is easier to use.

Is there any good way to override any type property?


Solution

  • Do not override default properties like that, because at "runtime" there is no guarantee req.cookies will exist. So to get correct type, do type narrowing.

    const handler = (req: Request, res: Response) => {
      if (!req.cookies) throw new Error('unauthorised')
      if (!req.cookies['cookie_name_1'] || typeof req.cookies['cookie_name_1'] !== 'string') throw new Error('unauthorised')
      const cookie_name_1 = req.cookies['cookie_name_1'] // cookie_name_1 is string
    }
    
    

    Above one ensures existence of req.cookies at both runtime & compilation.

    For auto-completion

    type MyCookies = {
      auth_token?: unknown
      some_token?: unknown
    }
    
    const handler = (req: Request, res: Response) => {
      if (!req.cookies) throw new Error('unauthorised')
      const cookies = req.cookies as MyCookies 
      if (typeof cookies.auth_token !== 'string') throw new Error('unauthorised')
      console.log(cookies.auth_token) // type is string & IDE will provide autocompletion
    }
    
    

    You could override Request['cookies'] to to have MyCookies type but there is huge chance you access those cookie in one place, aka inside a middleware function.