通过模块增强向现有 TypeScript 接口添加属性没有效果

Nat*_*end 6 typescript typescript-typings typescript2.0 typescript-definitions typescript-declarations

我有一个依赖于@types/hapi. 我想向该模块中定义的类之一添加一个属性。我尝试通过模块增强定义我的新属性:

// my-custom-hapi-typings.d.ts
import * as hapi from 'hapi';

declare module hapi {
    interface Server {
        myProperty: string;
    }
}
Run Code Online (Sandbox Code Playgroud)

这不会导致任何编译器错误,但也不会将该myProperty属性添加到Server类中。当我尝试像这样引用该属性时,我仍然在项目的其他地方遇到错误:

// my-other-file.ts
import * as hapi from 'hapi';

const server = new hapi.Server({ ... });

// error: Property 'myProperty' does not exist on type 'Server'.
server.myProperty = 'hello'; 
Run Code Online (Sandbox Code Playgroud)

为什么 TypeScript 编译器似乎忽略了我的.d.ts文件?我是否需要“导入”该文件或以某种方式让 TypeScript 编译器知道该文件存在?我的印象是,只需将.d.ts文件放在源目录中就足以让 TypeScript 接受这些增强。

Aar*_*all 6

这是你的问题:

declare module hapi {
Run Code Online (Sandbox Code Playgroud)

这实际上是定义一个namespace,使用早于 ES6 模块的旧语法,这些模块过去被称为“内部模块”。写作module hapi与写作相同namespace hapi,这是当今的首选语法。有关命名空间与模块的更多信息,请参见此处。

声明外部模块,您只需将模块名称放在引号中:

[...] 使用类似于环境命名空间的构造,但我们使用module关键字和模块的引用名称,这些名称将可供以后导入使用。

换句话说,只需加上hapi引号即可:

declare module "hapi"
Run Code Online (Sandbox Code Playgroud)

现在您有了一个环境my-custom-hapi-typings.d.ts不需要直接导入)外部模块定义(声明了import "hapi"给您提供的内容),并且您可以扩充其中声明的内容。

如果您将鼠标悬停在 Playground 中的module hapi和上,您将看到工具提示中的差异:module "hapi"

在此输入图像描述 在此输入图像描述

是的,由于其背后的历史,它是微妙且令人困惑的。