disclaimer: I am still a little fuzzy on variance in general...
My situation is as follows:
// index.ts
import express from 'express';
import {Request, Response} from 'express';
const app = express();
app.use(handler);
interface BetterRequest extends Request {
foo: string;
}
function handler(req: BetterRequest, res: Response) {
req.foo = 'bar';
}
// tsconfig.json
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"strict": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true
}
}
The error that I get is
[ts]
Argument of type '(req: BetterRequest, res: Response) => void' is not assignable to parameter of type 'RequestHandlerParams'.
Type '(req: BetterRequest, res: Response) => void' is not assignable to type 'RequestHandler'.
Types of parameters 'req' and 'req' are incompatible.
Type 'Request' is not assignable to type 'BetterRequest'.
Property 'foo' is missing in type 'Request'.
I understand what the error is saying and that I could either turn off those warnings from the tsconfig.json
file or by a line comment.
But that's not what I am after.
How do I properly write code to handle this situation?
is the following the only way?
// index.ts
function handler(req: Request, res: Response) {
const req2 = req as BetterRequest;
req2.foo = 'bar';
}
An explicit cast as you suggested is probably the best way if you know you are going to immediately set the foo
property and you want to be able to use the property from that point on without checking whether it is defined. Another approach is to declare the foo
property as optional; then a Request
can be implicitly converted to a BetterRequest
(so your handler can be implicitly converted to an Express handler), but the type of the foo
property will include undefined
and you'll have to deal with that every time you use the property.