I've tried to extend the standard Express Request interface, VSCode is picking up the declaration, but when I run ts-node index.ts I get :
/Users/vladr/.nvm/versions/node/v10.6.0/lib/node_modules/ts-node/src/index.ts:261
return new TSError(diagnosticText, diagnosticCodes)
^
TSError: ⨯ Unable to compile TypeScript:
index.ts(6,9): error TS2339: Property 'addedProperty' does not exist on type 'Request'.
index.ts(7,21): error TS2339: Property 'addedProperty' does not exist on type 'Request'.
However running tsc works fine. Also this is only a problem with ts-node@7, if I add TS_NODE_FILES=true it works as expected.
Here is a test repo to reporoduce the error:
https://github.com/vladrmnv/ts-node-broken-declaration-merging
Thanks for the detailed report. This is actually expected. See https://github.com/TypeStrong/ts-node#help-my-types-are-missing. Specifically, you're using typeRoots for a non-global definition, you should either write it as a global or use paths.
How to make it global? The README's linked TypeScript documentation doesn't mention how. Googling for "typescript global declaration" turns up this example. It's unclear what in all that file's names and comments does the trick. @vladrmnv did you figure it out?
@john-kurkowski That's a great point, feel free to make a PR updating the documentation around this. I do feel it's confusing from TypeScript's perspective and lacks some good documentation. The difference is around how you define it. Once you add export at the top-level, it turns into a "module". Same rules as TypeScript around regular .ts files.
Module:
export const bar: string
Global:
declare module "module" {
export const bar: string
}
In general, using a global is for a quick hack and may conflict some time. Using paths is a better long-term solution but requires more work usually to write it out correctly.
@blakeembrey could you provide an example of what you mean by "use paths"?
@vladrmnv paths is documented in the section of the README he linked to. See these lines.
@john-kurkowski yep, tried that, bug how would I merge my custom definition with the existing definitions? Such as in my express example?
@vladrmnv @john-kurkowski did anyone of you figured this out and could post a sample of what needs to be changed? I still don't get it. How can I add a prop to the express Request type declaration and have declaration merging working? I only get it to either pick up the default express declarations or my custom declaration but I don't get it to merge them.
Having the same issue, this fixed it https://github.com/TypeStrong/ts-node/issues/615#issuecomment-399808213
Basically, add the --files flag to ts-node to the get the pre 7.0.0 behaviour.
ts-node --files src/index.ts
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"]
Here is a working example for those who still struggling (like I was for past few hours):
If you are using "paths" in Afterwards I was able to run @types/express/index.d.ts: (MUST be \declare namespace Express { // MUST be namespace, and not declare module "Express" {
export interface Request {
Bla: string;
}
}
tsconfig.json:{
"compilerOptions": {
"module": "commonjs",
"target": "es2016",
"typeRoots" : [
"@types", // custom merged types MUST be first in a list
"node_modules/@types",
]
}
}
tsconfig.json you also MUST provide library mapping like that: "baseUrl": ".",
"paths": {
...
"express": ["@types/*"]
}
tsc -p ., ts-node index.ts and ts-node-dev index.ts successfully.
Extra information. TypeScript guys favor baseUrl + paths over typeRoots. The later is supposed to be used for migration. See https://github.com/microsoft/TypeScript/issues/22217#issuecomment-370019383.
@antonovicha this is awesome! you have really saved my day!!! thanks a lot
can't make it work for process.env
my @types/node/process.d.ts
declare namespace NodeJS {
export interface ProcessEnv {
TOTO: string;
}
}
my tsconfig.json
{
"compilerOptions": {
"module": "commonjs",
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"target": "es6",
"skipLibCheck": true,
"strict": true,
"noImplicitAny": true,
"allowJs": true,
"moduleResolution": "node",
"sourceMap": true,
"resolveJsonModule": true,
"outDir": "build",
"baseUrl": ".",
"rootDir": "src",
"experimentalDecorators": true,
"paths": {
"node": ["/src/v1/@types/node/*"]
}
},
"include": [
"src"
],
"exclude": [
"node_modules"
]
}
I'm getting "No overload matches this call." error on process.env.TOTO
@antonovicha
You really saved my day. Thanks a lot.
ts-node src/index.ts
All of the above doesn't work with me.
IDE said there are no errors.
But when I run scripts can't find the merged type.
https://github.com/TypeStrong/ts-node/issues/745#issuecomment-465027695
The above link was my candy.
Most helpful comment
Here is a working example for those who still struggling (like I was for past few hours):
@types/express/index.d.ts: (MUST be \tsconfig.json:If you are using "paths" in
tsconfig.jsonyou also MUST provide library mapping like that:Afterwards I was able to run
tsc -p .,ts-node index.tsandts-node-dev index.tssuccessfully.