Ts-node: Type declaration merging doesn't work

Created on 25 Oct 2018  Â·  15Comments  Â·  Source: TypeStrong/ts-node

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

invalid

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 \

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",
    ]
  }
}

If you are using "paths" in tsconfig.json you also MUST provide library mapping like that:

    "baseUrl": ".",
    "paths": {
      ...
      "express": ["@types/*"]
    }

Afterwards I was able to run tsc -p ., ts-node index.ts and ts-node-dev index.ts successfully.

All 15 comments

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):

@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",
    ]
  }
}

If you are using "paths" in tsconfig.json you also MUST provide library mapping like that:

    "baseUrl": ".",
    "paths": {
      ...
      "express": ["@types/*"]
    }

Afterwards I was able to run 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.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

sanex3339 picture sanex3339  Â·  4Comments

JoseLion picture JoseLion  Â·  3Comments

OliverJAsh picture OliverJAsh  Â·  3Comments

motss picture motss  Â·  4Comments

remojansen picture remojansen  Â·  4Comments