Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Type declaration merging doesn't work #715

Closed
vladrmnv opened this issue Oct 25, 2018 · 16 comments
Closed

Type declaration merging doesn't work #715

vladrmnv opened this issue Oct 25, 2018 · 16 comments
Labels

Comments

@vladrmnv
Copy link

vladrmnv commented Oct 25, 2018

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

@vladrmnv vladrmnv changed the title Type declaration doesn't work Type declaration merging doesn't work Oct 25, 2018
@blakeembrey
Copy link
Member

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.

@john-kurkowski
Copy link

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?

@blakeembrey
Copy link
Member

blakeembrey commented Oct 25, 2018

@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.

@vladrmnv
Copy link
Author

vladrmnv commented Nov 1, 2018

@blakeembrey could you provide an example of what you mean by "use paths"?

@john-kurkowski
Copy link

@vladrmnv paths is documented in the section of the README he linked to. See these lines.

@vladrmnv
Copy link
Author

vladrmnv commented Nov 2, 2018

@john-kurkowski yep, tried that, bug how would I merge my custom definition with the existing definitions? Such as in my express example?

@tbinna
Copy link

tbinna commented Feb 15, 2019

@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.

@anishpateluk
Copy link

anishpateluk commented Apr 1, 2019

Having the same issue, this fixed it #615 (comment)

Basically, add the --files flag to ts-node to the get the pre 7.0.0 behaviour.

ts-node --files src/index.ts

@saoudrizwan
Copy link

saoudrizwan commented Jun 20, 2019

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

@antonovicha
Copy link

Here is a working example for those who still struggling (like I was for past few hours):

@types/express/index.d.ts: (MUST be <module-name>/index.d.ts)

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.

@antonovicha
Copy link

Extra information. TypeScript guys favor baseUrl + paths over typeRoots. The later is supposed to be used for migration. See microsoft/TypeScript#22217 (comment).

@iriekun
Copy link

iriekun commented Oct 15, 2019

@antonovicha this is awesome! you have really saved my day!!! thanks a lot

@mi-mazouz
Copy link

mi-mazouz commented Mar 31, 2020

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

@jivan99
Copy link

jivan99 commented Sep 7, 2020

@antonovicha
You really saved my day. Thanks a lot.

@yusunglee2074
Copy link

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.

#745 (comment)
The above link was my candy.

@russell0430
Copy link

Here is a working example for those who still struggling (like I was for past few hours):

@types/express/index.d.ts: (MUST be /index.d.ts)

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.

this does work! Thanks a lot !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests