我有一个非常小的节点Typescript项目,具有以下结构:
尝试在index.ts文件中导入“diff”模块时,如下所示:
import * as diff from 'diff';
Atom-typescript突然失去了找到我的“fgtApp.Interfaces”命名空间的能力:
一旦我删除了import语句,node就能解析“fgtApp.Interfaces”命名空间,不会出现这样的问题:
这是atom-typescript中的错误还是我对导入这些外部模块的方式有所了解的错误?
答案 0 :(得分:6)
这并非特别是atom-typescript的问题。 atom-typescript插件使用官方的TypeScript语言服务(与Visual Studio相同),因此这在任何编辑器中都会出现问题。
问题在于,一旦指定了导入或导出,该文件就会变成一个模块("外部模块" pre-TypeScript 1.5)。这意味着当import * as diff from 'diff';
存在时,index.ts
中声明的内容仅变为本地内容,并且不会考虑/合并到全局名称空间中。
TypeScript规范,第11.1节: ...包含至少一个外部导入声明,导出分配或顶级导出声明的源文件被视为单独的外部模块。在外部模块中声明的实体仅在该模块的范围内,但可以使用导入声明将导出的实体导入到其他模块中
当您不使用外部模块时,TypeScript允许不同文件中的命名空间相互构建。一旦开始使用外部模块,不再使用变通方法就不会出现这种情况。在这种情况下,通常最好切换到使用外部模块 - 如果您正在制作Node项目,这一点非常简单,因为您不必担心捆绑。
而不是"深命名空间" (例如fgtApp.category.thing)就像C#和.NET一样鼓励 - 开始考虑将每个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;
}
<强> 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;
<强> index.ts 强>
import {FgtService} from './Service';
const myService = new FgtService();
console.log(myService.authenticateDisable);