I'm using Express and I'm trying to explicitly define res.locals
. In the @types/express package, Express.Response.locals is any
, so I can't seem to overwrite it:
types/express/index.d.ts:
declare namespace Express {
interface Response {
locals: {
myVar: number
}
}
}
My Middleware:
import * as express from 'express'
function middleware(
req: express.Request,
res: express.Response,
next: express.nextFunction
) {
res.locals.myVar = '10' // I want this to throw a compiler error
next()
}
I want my wrong assignment of res.locals.myVar
to error, but res.locals
is still any
according to my autocompletion.
How can I remove any
and completely replace it?
Use the Omit utility type to override the type of an interface property, e.g. interface SpecificLocation extends Omit<Location, 'address'> {address: newType} . The Omit utility type constructs a new type by removing the specified keys from the existing type.
An interface can be extended by other interfaces. In other words, an interface can inherit from other interface. Typescript allows an interface to inherit from multiple interfaces. Use the extends keyword to implement inheritance among interfaces.
TypeScript lets you augment an interface by simply declaring an interface with an identical name and new members. This lets you extend existing JavaScript code without creating a new named type.
Hence interface works better when using objects and method objects. Therefore it is our choice to choose between types or interface according to the program needs. In Typescript, union types can contain one or more types using the “ | ” keyword, where we can have a new union type by combining two interfaces.
I recently ran into this issue and managed to resolve it by creating an index.d.ts
in my src folder to overwrite res.locals, my implementation looked like this:
// src/index.d.ts
import 'express';
interface Locals {
message?: string;
}
declare module 'express' {
export interface Response {
locals: Locals;
}
}
Make sure you also have it included in your tsconfig.json, e.g
// somewhere in your tsconfig.json
"include": [
"src/**/*.ts"
]
You would use the interface just as you would normally
import { Request, Response, NextFunction } from 'express';
export const handler = (req: Request, res: Response, next: NextFunction) => {
// should be typed
res.locals.message = 'hello'
}
Hope this helps!
Unfortunately there is no way to override any using interface merging. You can so some surgery on the type and replace the type using mapped and conditional types:
import * as express from 'express'
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>
type MyResponse = Omit<express.Response, "locals"> & {
locals: {
myVar: number
}
}
function middleware(
req: express.Request,
res: MyResponse,
next: express.NextFunction
) {
res.locals.myVar = '10' // error now
next()
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With