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

为什么导入节点模块会破坏atom Typescript中的内部Typescript命名空间?,typescript,Typescript,我有一个非常小的节点Typescript项目,其结构如下: 尝试在my index.ts文件中导入“diff”模块时,如下所示: import * as diff from 'diff'; Atom typescript突然无法找到我的“fgtap.Interfaces”命名空间: 只要我删除import语句,node就能够解决“fgtap.Interfaces”名称空间中的任何问题: import * as diff from 'diff'; 这是atom typescript中的一

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

尝试在my index.ts文件中导入“diff”模块时,如下所示:

import * as diff from 'diff';
Atom typescript突然无法找到我的“fgtap.Interfaces”命名空间:

只要我删除import语句,node就能够解决“fgtap.Interfaces”名称空间中的任何问题:

import * as diff from 'diff';


这是atom typescript中的一个错误,还是我对导入这些外部模块的工作方式的理解中的一个错误?

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

问题在于,一旦指定了导入或导出,该文件就会变成一个模块(“外部模块”pre-TypeScript 1.5)。这意味着当
import*作为diff从'diff'导入时存在,在
index.ts
中声明的内容仅成为本地的,不考虑/合并到全局命名空间中

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

当您不使用外部模块时,TypeScript允许不同文件中的名称空间相互构建。一旦开始使用外部模块,如果不使用变通方法,情况就不再如此了。在这种情况下,通常最好切换到使用外部模块——如果您正在创建节点项目,这尤其容易,因为您不必担心绑定

不要像C#和.NET这样的“深层名称空间”(例如fgtap.category.thing),而是开始将每个TypeScript源文件看作自己的模块。如果确实需要层次结构,请使用文件夹结构实现层次结构

即使
noImplicitAny
处于活动状态,此代码仍能正常工作:

接口。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;
}
// 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;
import {FgtService} from './Service';

const myService = new FgtService();
console.log(myService.authenticateDisable);
服务.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;
}
// 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;
import {FgtService} from './Service';

const myService = new FgtService();
console.log(myService.authenticateDisable);
index.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;
}
// 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;
import {FgtService} from './Service';

const myService = new FgtService();
console.log(myService.authenticateDisable);

因为它变成了一个文件模块:@basarat所以这不可能工作?看起来这确实有助于保持代码整洁。我在这里写了一个类似的问题:@askanison4可能的解决方法是将
import*作为diff从'diff'中删除diff.property
;你提到了变通办法。他们会是什么?注意:我在这里提出了一个类似的问题:解决方法的一个示例可能是以全局名称空间的方式编写所有代码,然后编写一个预处理器,以外部样式将名称空间合并到一组模块下。我并不是说这很容易,也不是说工具很好。