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 any
type is the top type of typescript so customized cookies
property 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?
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.