上面的 Murat Karagöz 回答指出了正确的方向,这个回答将提供实际代码以及我们将使用 declare 的最小示例。
Here 是一个非常简单的 npm 模块:只有一个 index.js 文件,它使用一种方法导出一个对象。这里没有类型声明,因为它只是 JS。
const item = {
price: 5,
name: 'item1',
};
export const MyModuleObject = { method: () => item };
Here 是一个非常简单的 TypeScript npm 项目,有一个依赖项:上面链接的 JS 项目。因此后者是一个没有类型的导入 npm 模块。这里是TS项目中的index.ts文件:
/// <reference path="index.d.ts"/>
import { MyModuleObject } from 'npmModule';
import { LocalModuleObject } from './module';
// Without the "reference path" line, TS complains in line 3 that it could not find a declaration file for 'npmModule'.
// In this case, the import has type any, so TS does not complain about the call below to an inexistent method.
// When we uncomment line 1, we get a TS error on line 8: property 'test' does not exist on type { method: ... }
MyModuleObject.test();
// TS complains that test does not exist on type { method: ... }
// Here we did not need to have a `declare` statement in a type definitions file for TS to know this because here TS is
// using contextual typing:
LocalModuleObject.test();
下面是index.d.ts的代码:
declare module "npmModule" {
export const Item: {
price: number,
name: string
}
export const MyModuleObject: {
method: () => Item
}
}
还有./module的代码:
export const LocalModuleObject = { method: () => 10 };
这是为什么使用声明的示例
- 我把它放在index.ts 的cmets 中,但让我用更多的话来解释它。 index.ts 正在从外部模块(node_modules 中的一个)导入一个对象,并从本地模块 (./module.js) 导入另一个对象。两个模块都使用一种名为method 的方法导出对象。在index.ts 中,我在每个对象上调用了一个不存在的方法test。
TS 在本地模块的导入上使用上下文类型,因此它知道test 不存在于对象上。在外部模块中导入对象时不会发生这种情况:此导入是使用类型 any 导入的。因此,TS 不会抱怨调用不存在的方法test。但是,它确实抱怨没有为外部模块输入类型,所以这是暗示正在使用隐式 any。
我们可以通过定义一个为外部库提供类型的index.d.ts 来解决后一种问题。这是使用declare module 的地方:它声明了模块npmModule 导出的内容; npmModule 是外部导入。在 index.ts 中,我们必须添加行 /// <reference path="index.d.ts"/> 以便 TS 知道在哪里查找类型。