Having error "Module 'name' resolves to an untyped module at..." when writing custom TypeScript definition file
Asked Answered
S

5

132

I can't find TypeScript definition @type/{name} for one of my installed NodeJS packages, so I attempt to write a d.ts file for it, and put the file in {project root}\typings folder. This is how I do:

// My source code: index.ts
import Helper from 'node-helper-lib';


// My definition: \typings\node-helper-lib.d.ts
declare....(something else)

declare module 'node-helper-lib' {
   class Helper { ... }
   export = Helper;
}

However, Visual Studio Code keeps yielding this error and puts red line under declare module 'node-helper-lib':

[ts] Invalid module name in augmentation. Module 'node-helper-lib' resolves to an untyped module at '{project path}\node_modules\node-helper-lib\index.js', which cannot be augmented.

Isn't it legit that because the library is untyped, so I should be allowed to add typing to it?

UPDATE:

I am using:

  • TypeScript: 2.1.4
  • Visual Studio Code: 1.9.1
  • Node JS: 6.9.4
  • Windows 10 x64
Smaragdite answered 22/2, 2017 at 9:57 Comment(0)
S
108

After some tries and errors, I found that augmentation means "declaring a module in the same file with other module declaration(s)".

Therefore if we want to write a definition file for an untyped 3rd-party JavaScript library, we must have ONLY ONE declare module 'lib-name' in that file, and 'lib-name' must exactly match the library name (can be found in its package.json, "name" property).

On the other hand, if a 3rd-party library already has definition file .d.ts included, and we want to extend its functionalities, then we can put the additional definition in another file that we create. This is called augmenting.

For example:

// These module declarations are in same file, given that each of them already has their own definition file.
declare module 'events' {
   // Extended functionality
}

declare module 'querystring' {
   // Extended functionality        
}

declare module '...' { ... }

I leave my discovery here just in case somebody has same question. And please correct me if I missed something.

Smaragdite answered 1/3, 2017 at 3:40 Comment(7)
What should I do if a 3rd-party library already has definition file .d.ts included, but I would like to ignore it and use a custom one?Parrotfish
I'm not sure. Did you try <reference path=".." /> pointing to custom definition?Smaragdite
I'm trying to write a definition file for a completely untyped npm module, supertest — TypeScript's complaint doesn't even make sense, how can I not augment something that doesn't even have a declaration? I thought I've wrote custom definition files like this many times... [ts] Invalid module name in augmentation. Module 'supertest' resolves to an untyped module at '/home/chase/Desktop/projects/formuoli/node_modules/supertest/index.js', which cannot be augmented. — unfortunately @types/supertest is broken by including DOM libraries rendering it broken.. looks like I'm out of luckMott
@ChaseMoskal: In your file .d.ts, maybe you should just move all the import into the declare module "moduleName" {}.Cronyism
@Cronyism that was exactly it, all import calls must go inside declare module 'module' {} scope. the error is misleading at bestAllimportant
typescript does the same thing if you put the import statements required by your module outside of the declare module instead of inside it. Such unintuitive odd behavior (sorry for ranting here).Floatstone
This answers https://mcmap.net/q/172523/-having-error-quot-module-39-name-39-resolves-to-an-untyped-module-at-quot-when-writing-custom-typescript-definition-fileFurring
D
227

The actual solution is given in a comment by @Paleo in @hirikarate's answer:

Imports should be declared inside the module declaration.

Example:

declare module 'node-helper-lib' {
   import * as SomeThirdParty from 'node-helper-lib';
   interface Helper {
       new(opt: SomeThirdParty.Options): SomeThirdParty.Type
   }
   export = Helper;
}
Doud answered 17/2, 2018 at 22:13 Comment(2)
This is a catch-22. Can't import the somemodulehere because it doesn't have a declaration. Can't create a declaration to augment it because it's an untyped modue. The example above would be throwing 2 errors. The first being that you cannot augment the node-helper-lib the 2nd being that it cannot find the declaration file for the import.Mcintyre
It may have changed since I wrote that.Doud
S
108

After some tries and errors, I found that augmentation means "declaring a module in the same file with other module declaration(s)".

Therefore if we want to write a definition file for an untyped 3rd-party JavaScript library, we must have ONLY ONE declare module 'lib-name' in that file, and 'lib-name' must exactly match the library name (can be found in its package.json, "name" property).

On the other hand, if a 3rd-party library already has definition file .d.ts included, and we want to extend its functionalities, then we can put the additional definition in another file that we create. This is called augmenting.

For example:

// These module declarations are in same file, given that each of them already has their own definition file.
declare module 'events' {
   // Extended functionality
}

declare module 'querystring' {
   // Extended functionality        
}

declare module '...' { ... }

I leave my discovery here just in case somebody has same question. And please correct me if I missed something.

Smaragdite answered 1/3, 2017 at 3:40 Comment(7)
What should I do if a 3rd-party library already has definition file .d.ts included, but I would like to ignore it and use a custom one?Parrotfish
I'm not sure. Did you try <reference path=".." /> pointing to custom definition?Smaragdite
I'm trying to write a definition file for a completely untyped npm module, supertest — TypeScript's complaint doesn't even make sense, how can I not augment something that doesn't even have a declaration? I thought I've wrote custom definition files like this many times... [ts] Invalid module name in augmentation. Module 'supertest' resolves to an untyped module at '/home/chase/Desktop/projects/formuoli/node_modules/supertest/index.js', which cannot be augmented. — unfortunately @types/supertest is broken by including DOM libraries rendering it broken.. looks like I'm out of luckMott
@ChaseMoskal: In your file .d.ts, maybe you should just move all the import into the declare module "moduleName" {}.Cronyism
@Cronyism that was exactly it, all import calls must go inside declare module 'module' {} scope. the error is misleading at bestAllimportant
typescript does the same thing if you put the import statements required by your module outside of the declare module instead of inside it. Such unintuitive odd behavior (sorry for ranting here).Floatstone
This answers https://mcmap.net/q/172523/-having-error-quot-module-39-name-39-resolves-to-an-untyped-module-at-quot-when-writing-custom-typescript-definition-fileFurring
R
9

The issue for me was that I was trying to declare the module in a .ts file. I changed it to .d.ts and it all worked just fine.

Ranson answered 31/5, 2021 at 18:14 Comment(0)
G
6

I was getting that error message too. The issue for me was that I was trying to declare another module in an existing type definition file that had a module declaration in it. After I moved the new module declaration to a new file, the error went away.

Gutow answered 1/11, 2018 at 22:39 Comment(0)
J
-1

For me, it happened with npm 'node-apple-receipt-verify' package:

Invalid module name in augmentation. Module 'node-apple-receipt-verify' resolves to an untyped module at '/node_modules/node-apple-receipt-verify/index.js', which cannot be augmented.ts(2665)

Only working solution is installing it like this:

npm install --save-dev @types/node-apple-receipt-verify
Johnstone answered 24/3, 2023 at 10:32 Comment(1)
Not helpful if there isn't a declaration file in the @types repository.Helix

© 2022 - 2024 — McMap. All rights reserved.