为什么导入节点模块会破坏atom-typescript中的内部Typescript命名空间?

sla*_*shp 6 typescript

我有一个非常小的节点Typescript项目,具有以下结构:

应用结构

尝试在我的index.ts文件中导入"diff"模块时,如下所示:

import * as diff from 'diff';
Run Code Online (Sandbox Code Playgroud)

Atom-typescript突然失去了定位我的"fgtApp.Interfaces"命名空间的能力:

丢失内部命名空间的自动完成功能

一旦我删除了import语句,node就能解析"fgtApp.Interfaces"命名空间,不会出现这样的问题:

自动完成工作正常,无需导入声明

这是atom-typescript中的错误还是我对导入这些外部模块的方式的理解中的错误?

NYC*_*Net 6

这不是atom-typescript的具体问题.atom-typescript插件使用官方的TypeScript语言服务(与Visual Studio相同),因此这在任何编辑器中都是一个问题.

问题是,一旦指定了导入或导出,该文件就变成了一个模块(TypeScript 1.5之前的"外部模块").这意味着当import * as diff from 'diff';存在时,声明的内容index.ts仅变为本地,并且不考虑/合并到全局名称空间中.

TypeScript规范,第11.1节: ...包含至少一个外部导入声明,导出分配或顶级导出声明的源文件被视为单独的外部模块.在外部模块声明的实体仅在该模块的范围内,但可以使用导入声明将导出的实体导入到其他模块中

当您不使用外部模块时,TypeScript允许不同文件中的命名空间相互构建.一旦开始使用外部模块,不再使用变通方法就不会出现这种情况.在这种情况下,通常最好切换到使用外部模块 - 如果您正在制作Node项目,这一点特别容易,因为您不必担心捆绑.

而不是像C#和.NET那样的"深度命名空间"(例如fgtApp.category.thing)鼓励 - 开始将每个TypeScript源文件视为自己的模块.如果您确实需要层次结构,请实现具有文件夹结构的层次结构.

即使noImplicitAny激活,此代码也可以正常工作:

interfaces.d.ts

// Notice that this is a d.ts file.  Since it will only contain interfaces,
//  making it a d.ts file means TypeScript doesn't have to worry about
//  emitting it and you also can't accidentally put executable code here.
export interface IFgtService {
    authenticateDisable: boolean;
    failedAttempt: boolean;
    authenticate: (username: string, password: string) => boolean;
}

export interface IAnotherInterfaceAsAnExample {
    isCool: boolean;
}
Run Code Online (Sandbox Code Playgroud)

service.ts

// since there is no "relative path", diff will come from node_modules.
import * as diff from 'diff';
// since there IS a relative path, interfaces will come from ./interfaces.d.ts
import * as interfaces from './interfaces';

// You can still use namespaces inside an "external module", but mainly they
//  serve as a convenient way to bundle stuff for a one-line export (see
//  the last line of this file).
namespace Service {
  export class FgtService implements interfaces.IFgtService {
    authenticateDisable = true;
    failedAttempt = true;
    authenticate = (username: string, password: string) => {
      let d = diff.d;
      return true;
    }
  }
}
export = Service;
Run Code Online (Sandbox Code Playgroud)

index.ts

import {FgtService} from './Service';

const myService = new FgtService();
console.log(myService.authenticateDisable);
Run Code Online (Sandbox Code Playgroud)