如何在d.ts中扩展TypeScript接口

16

我的使用场景:请求的RequestResponse类型定义缺少body属性,如下所示:

declare namespace request {

    // ...

    export interface RequestResponse extends http.IncomingMessage {
        request: Options;
    }

    // ...

}
declare var request: request.RequestAPI<request.Request, request.CoreOptions, request.RequiredUriUrl>;
export = request;

我正在尝试通过创建一个名为request-fix.d.ts的文件来修复它,内容大致如下:
import * as http from 'http';
declare namespace request {
    export interface RequestResponse extends http.IncomingMessage {
        body: any;
    }
}

但是没有产生任何效果。我的最终目标是,在我的app.ts中,我可以这样做:
import * as rp from 'request-promise';
import { RequestResponse } from 'request';

let response = rp.get(url);

response.statusCode; // works
response.body; // doesn't compile

当然,我可以为DefinitelyTyped做贡献 :) 但是这个问题是关于增强RequestResponse接口的。

  1. request-fix.d.ts 中缺少对 RequestResponse 的 export
  2. 是否将 request-fix.d.ts 添加到 tsconfig.jsonfiles 中?
- artem
“.d.ts”文件即使我在里面放入无意义的内容,也不会产生任何编译时错误。在我的tsconfig.json中:“files”: [“app.ts”,“request-fix.d.ts”]。尝试将“///<reference ...>”添加到我的app.ts中,但没有任何区别。 - Borek Bernard
哦,skipLibCheck 是 true。这让我前进了一步,至少我可以看到更多的错误了。 - Borek Bernard
现在 .d.ts 文件肯定会编译,但是编译器仍然无法识别 .body 属性。 - Borek Bernard
你是想用自己的版本覆盖他们的“RequestResponse”类型声明文件吗? - Shaun Luttin
@ShaunLuttin 不,我正在尝试增强它。 - Borek Bernard
2个回答

23

这是在request-fix.d.ts中起作用的组合:

import * as http from 'http';

declare module 'request' {
    export interface RequestResponse extends http.IncomingMessage {
        body: any;
    }
}
为了扩充现有模块,必须使用declare module而非declare namespace,并且它必须出现在编译后的源代码中的某个模块范围内。也就是说,request-fix.d.ts 必须具有某些导入以将其转换为模块,就像您在代码中使用import * as http from 'http'一样。如果declare module出现在非模块范围内(就像我在第一个回答尝试中所做的那样),它只会声明一个单独的、不相关的模块,如这里所述。

它对我不起作用。我创建了这个小仓库来演示问题:https://github.com/borekb/ts-augmentation-demo - Borek Bernard
导入必须在顶层,我已经更新了带有可工作解决方案的GitHub演示:https://github.com/borekb/ts-augmentation-demo。(如果您更新了代码,我将把它标记为答案。感谢您的帮助!) - Borek Bernard
1
重要提示:declare module requestdeclare module "request"是不同的。这个问题曾让我感到困惑了一段时间。(有引号时,它会尝试将模块解析为现有的模块匹配项;没有引号时,它会假定您正在声明一个全新的模块/名称空间) - Venryx

4

@artem是正确的,+1,我只想补充一点,你不应该忘记命名空间。

例如,这是如何将className属性添加到来自material-uiCardTitle组件中的:

declare module "material-ui" {
    namespace __MaterialUI {
        namespace Card {
            export interface CardTitleProps {
                className?: string;
            }
        }
    }
}

解释很简单..模块和命名空间只存在于运行时,并且会自动合并。

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