当“不要这样做”不是一个选项时,如何将 Typescript 命名空间与外部模块混合

Posted

技术标签:

【中文标题】当“不要这样做”不是一个选项时,如何将 Typescript 命名空间与外部模块混合【英文标题】:How do I mix Typescript namespaces with External modules when "Don't do it" is not an option 【发布时间】:2017-03-26 10:52:03 【问题描述】:

情况

我有一个使用命名空间编写的 Typescript 应用程序。我想将其中的一些逻辑(Google OAuth)从客户端移到节点服务中。我已经为 here 创建了一个几乎完整的项目。

这个新项目有一个节点组件,它将使用密钥向 google 发出授权请求,以及一个客户端组件,可以被其他与服务器通信的应用程序重用。我还有一个 testHarness 应用程序,它使用此客户端对其进行测试,并确保我可以在基于命名空间的应用程序中使用它。

我有一些客户端和服务器都使用的共享接口。

我希望我的客户端代码可用于使用 externam 模块和命名空间的项目 - 即我现有的项目。

应该可以

我读过很多地方

不要在外部模块中使用“命名空间”。

不要这样做。

说真的。停止。

比如answer,但我仍然相信这一定是可能的。我认为这是因为在我的项目中我依赖于 RxJs。我的 node_modules 文件夹中的这个项目被客户端和服务器使用。

我尝试过的

在我的project 中有一个contracts.d.ts 文件,我想在客户端和服务器之间共享它。

堆栈溢出

我看了这个问题:

Typescript es6 import module "File is not a module error"

让我的合同看起来像这样:

// test.js - exporting es6
export module App 
  export class SomeClass 
    getName(): string 
      return 'name';
    
  
  export class OtherClass 
    getName(): string 
      return 'name';
    
  

然后尝试了列出的各种导入方法:

import * as app1 from "./test";
import app2 = require("./test");
import App from "./test";

我让这些中的每一个都能正常工作,以便我的服务器和客户端正确编译,但是一旦我尝试编译我的 testHarness 应用程序 - 它使用命名空间 - 它就失败了:

src/testHarness/testHarness.ts(4,38): error TS2304: Cannot find name 'PricklyThistle'.
src/testHarness/testHarness.ts(4,38): error TS2503: Cannot find namespace 'PricklyThistle'.

从 node_modules 复制声明文件

正如我所说,我确信这是可能的,因为我导入 node_modules 的依赖项被我的客户端和服务器项目使用,并且我的客户端仍然可以与内部命名空间一起使用。

为了走这条路,我在 Rx ts 文件夹中编辑了一个 d.ts 文件并添加了一个新界面。我验证了客户端和服务器都可以使用这个接口,并且我的 testHarness 应用程序(带有命名空间)可以编译。一切都很好!

然后我将此编辑后的文件复制到我的公共文件夹中。我不得不重命名模块以避免冲突,但后来我得到:

src/node/youTubeAuthenticationServer.ts(3,23): error TS2306: File '/src/common/rx.test.d.ts' is not a module.

我编辑的声明文件如下所示:

declare module RxTest 

    export interface TestInterface
        propertyOne: string;
        propertyTwo: number;
    


declare module "rx.test"  export = RxTest; 

解决方法

现在我刚刚复制了两个应用程序使用的接口。这行得通,只有 2 个小接口,所以没什么大不了的。不过,这很令人讨厌。 node 的一大优点是它使用与浏览器相同的语言。如果你不能分享不好的代码。我还有其他更大的代码库,我想做类似的事情,在这些情况下复制代码将不是一个可行的解决方案。

我从事的任何新项目都将专门使用外部模块,但在使用遗留代码时,这并不总是可行的。

我真的希望有人可以提供帮助。

谢谢

【问题讨论】:

【参考方案1】:

如果您的问题有点令人困惑,说明您所拥有的内容描述过多而示例(代码/配置)过少。

尝试这样做:

declare module "rx.test" 
    export interface TestInterface
        propertyOne: string;
        propertyTwo: number;
    

如果这不起作用,请编辑您的问题并添加您拥有的目录结构、您拥有的 tsconfig.json 文件、解释您的构建方式(tsc、gulp 等)等等。

【讨论】:

以上是关于当“不要这样做”不是一个选项时,如何将 Typescript 命名空间与外部模块混合的主要内容,如果未能解决你的问题,请参考以下文章

setoptsocket函数

在页面刷新时保持选择选项

如何让 $(/bin/printf -6) 返回 -6 而不是认为 -6 是一个选项

当用户选择“在新选项卡中打开”/“在新窗口中打开”而不是使用 html/javascript 点击时如何到达所需的页面

当超过最大宽度时,如何选择选项?

tslint:禁用在 vscode 中不起作用