编写自定义TypeScript定义文件时遇到错误“模块'name'解析为未定义的模块...”

129

我找不到已安装的 NodeJS 包中的 TypeScript 定义@type/{name},因此我尝试为其编写一个d.ts文件,并将该文件放在{project root}\typings文件夹中。我的具体做法如下:

// 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;
}

但是,Visual Studio Code一直出现这个错误,并在declare module 'node-helper-lib'下方放置红线:

[ts] 在增量中无效的模块名称。模块“node-helper-lib”解析为未经分类的模块,位于“{project path}\node_modules\node-helper-lib\index.js”,无法进行增强。

难道不应该合法吗?因为库是没有类型的,所以我应该被允许添加类型到它里面吗?

更新:

我正在使用:

  • TypeScript:2.1.4
  • Visual Studio Code:1.9.1
  • Node JS:6.9.4
  • Windows 10 x64
5个回答

225

实际的解决方案在@hirikarate答案的评论中由@Paleo提供:

导入应在模块声明内部声明。

例如:

declare module 'node-helper-lib' {
   import * as SomeThirdParty from 'node-helper-lib';
   interface Helper {
       new(opt: SomeThirdParty.Options): SomeThirdParty.Type
   }
   export = Helper;
}

12
这是个进退维谷的情况。无法导入 somemodulehere,因为它没有声明。无法创建一个声明来扩充它,因为它是一个“未类型化的模块”。上面的例子会抛出两个错误:第一个是你不能扩充 node-helper-lib,第二个是找不到要导入的声明文件。 - Douglas Gaskell
1
自我写下这段代码以来,它可能已经发生了变化。 - Lee Benson

107

在尝试和错误后,我发现 augmentation 的意思是“在同一文件中声明一个模块与其他模块的声明”。

因此,如果我们想为一个未经类型定义的第三方JavaScript库编写一个定义文件,我们必须在该文件中只有一个declare module 'lib-name',而且'lib-name'必须与库名称完全匹配(可以在其package.json文件中找到"name"属性)。

另一方面,如果一个第三方库已经有了定义文件.d.ts,而我们想扩展其功能,则可以将附加的定义放在我们创建的另一个文件中。这被称为augmenting

例如:

// 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 '...' { ... }

我在这里分享我的发现,以防有人有同样的问题。如果我漏掉了什么,请指正。


1
如果一个第三方库已经包含了定义文件.d.ts,但是我想忽略它并使用自定义的文件,我应该怎么办? - Alen Liang
27
我正在尝试为一个完全没有类型的npm模块supertest编写定义文件。 TypeScript的报错甚至毫无意义,因为我怎么可能增强一个连声明都没有的东西呢?我认为我已经写过很多类似这样的自定义定义文件了... [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.——不幸的是,@types/supertest包含DOM库,导致其无法使用...看起来我运气不太好。 - ChaseMoskal
41
在您的 .d.ts 文件中,也许您应该将所有的 import 移动到 declare module "moduleName" {} 中。 - Paleo
23
没错,所有的 import 调用都必须在 declare module 'module' {} 的范围内。这个错误提示最多是误导性的。 - pocesar
3
如果你把你的模块所需的“import”语句放在“declare module”之外而不是之内,TypeScript会做相同的事情。这种不直观的奇怪行为(抱歉在此发牢骚)。 - binki
显示剩余3条评论

7

我遇到的问题是尝试在一个 .ts 文件中声明模块。我将文件改为 .d.ts,问题就得到了解决。


5
我也曾遇到过这个错误消息。对我来说,问题在于我试图在一个已有模块声明的类型定义文件中声明另一个模块。当我将新的模块声明移动到一个新文件中后,错误消失了。

-1

对我来说,这与npm的'node-apple-receipt-verify'包有关:

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)

唯一可行的解决方案是这样安装:

npm install --save-dev @types/node-apple-receipt-verify

1
如果在@types存储库中没有声明文件,那就没有什么帮助。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接