// ./typings/express/index.d.ts
declare namespace Express {
export interface Request {
token?: string
}
}
Example usage:
import * as express from 'express'
(req: express.Request, res: express.Response, next: express.NextFunction) => {
const foo = req.token
}
It does work if I compile directly (tsc -p .), it does work in Visual Code, but when I try to run with ts-node I always get:
error TS2339: Property 'token' does not exist on type 'Request'.
Any idea how can I make it work with ts-node?
Versions: [email protected] [email protected]
What鈥檚 your tsconfig.json?
{
"compilerOptions": {
"module": "commonjs",
"target": "es6",
"noImplicitAny": false,
"sourceMap": true,
"outDir": "dist",
"experimentalDecorators": true,
"esModuleInterop": true
},
"exclude": ["node_modules"]
}
I also tried with "typeRoots": ["./node_modules/@types", "./typings"]
@brunolm That wouldn't work because it'd just discover the first one, not all of them. You can always use the /// <reference /> directive to resolve the one you specifically want to extend (and put your typeRoots first, otherwise you're just resolving @types anyway - it may even work by just switching the order of typeRoots above and no need for reference since one is a module and the other definition is global).
Oh, also, you probably should just put your overrides in a different folder and it would be a non-issue. The problem is the conflict between two Express packages being resolved, but you can create a different package named something to do with your app or anything else that doesn鈥檛 conflict.
As this is confusing a lot of people to get right, I'd suggest setting up a working example in the docs
I don't fully understand why that's required now. I can confirm that this worked before:
versions
"typescript": "2.3.4",
"ts-node": "3.0.4",
tsconfig.json
{
"compilerOptions": {
"module": "commonjs",
"target": "es6",
"noImplicitAny": false,
"sourceMap": true
}
}
typings/foo.d.ts
declare module Express {
export interface Request {
knex: any;
config: any;
client: { id: number; name: string; };
}
}
Please see the README and CHANGELOG, and possibly search past issues to find why it was changed.
There is also an example in the README for adding custom types and modules. If you鈥檇 like to expand upon it, please feel free to submit a PR!
Just checked and we should invert the resolution order of types so it works as expected here.
Edit: The reason for the change is also in the README.
With --files in ts-node command local declaration files are recognized. Example command: ts-node --files src/index.ts
Can you guys @3mard @blakeembrey tell WHY this works? I would like understand more :) Also is this the best solution for this problem or is it only a workaround?
I gave up and started to do this:
req['token'] = 'foo'
And then casting to something when needed.
@henrikra I think this is a design decision that was made to optimize ts-node (why include .d.ts files that your app are not using anyway ?)
https://github.com/TypeStrong/ts-node/blob/master/src/index.ts#L481
@brunolm @henrikra I created this repo example https://github.com/3mard/ts-node-example for extending express request
Thanks to this comment by @blakeembrey, I got my declaration merges working! All you need to do is put "./typings" before "./node_modules/@types".
"typeRoots": ["./typings", "./node_modules/@types"]
@saoudrizwan Thanks it works :)
This worked for me:
declare module 'express-serve-static-core' {
interface Request {
foo?: string
}
}
@marcosfede your code makes everything be an any

If I delete your file the types work again.
Thanks to this comment by @blakeembrey, I got my declaration merges working! All you need to do is put
"./typings"before"./node_modules/@types"."typeRoots": ["./typings", "./node_modules/@types"]
Still not working

I solved this issues like this
(req as any).something = object;
it works for me
Thanks to this comment by @blakeembrey, I got my declaration merges working! All you need to do is put
"./typings"before"./node_modules/@types"."typeRoots": ["./typings", "./node_modules/@types"]Still not working
I solved this issues like this
(req as any).something = object;
it works for me
Same. I can't make it work. Neither solution helps. Yours is an ugly hack but works for sure.
My problem is that VSCode recognizes it, and all is green. But when I try to run it with ts-node, it gives the error.
The following worked for me:
// project-root/src/types/express/index.d.ts
declare global {
namespace Express {
interface Request {
token?: string
}
}
}
And then run
ts-node --files ./src/server.ts
As ts-node does not use files because of slows startup time, we need to tell it explicitly. Hence '--_files_' is necessary here.
VSCode gives me:
Augmentations for the global scope can only be directly nested in external modules or ambient module declarations.ts(2669)
You need to import or export something to indicate that the file is a module.
If you are not importing anything then simply add
export {};
in that file, then the error should be gone.
To help anyone who is just looking for something else to try here is what worked for me when trying to extend ExpressJS' Request. I had to have tried more than a dozen things before getting this to work:
"typeRoots": [
"./node_modules/@types",
"./your-custom-types-dir"
]
declare global {
namespace Express {
interface Request {
customBasicProperty: string,
customClassProperty: import("../path/to/CustomClass").default;
}
}
}
{
"restartable": "rs",
"ignore": [".git", "node_modules/**/node_modules"],
"verbose": true,
"exec": "ts-node --files",
"watch": ["src/"],
"env": {
"NODE_ENV": "development"
},
"ext": "js,json,ts"
}
Most helpful comment
To help anyone who is just looking for something else to try here is what worked for me when trying to extend ExpressJS' Request. I had to have tried more than a dozen things before getting this to work: