为什么导入节点模块会破坏 atom-typescript 中的内部 Typescript 命名空间? [英] Why does importing a node module break my internal Typescript namespaces in atom-typescript?

查看:18
本文介绍了为什么导入节点模块会破坏 atom-typescript 中的内部 Typescript 命名空间?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a very small node Typescript project with the following structure:

当尝试像这样在我的 index.ts 文件中导入diff"模块时:

When attempting to import the "diff" module in my index.ts file like so:

import * as diff from 'diff';

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

Atom-typescript suddenly loses the ability to locate my "fgtApp.Interfaces" namespace:

一旦我删除了 import 语句,节点就能够解决fgtApp.Interfaces"命名空间,没有像这样的问题:

As soon as I remove the import statement, node is able to resolve the "fgtApp.Interfaces" namespace no issue like so:

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

Is this a bug in atom-typescript or a bug in my understanding of the way importing these external modules work?

推荐答案

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

This isn't specifically a problem with atom-typescript. The atom-typescript plugin uses the official TypeScript language service (Same as Visual Studio), so this would be a problem in any editor.

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

The trouble is that once you have an import or export specified, the file becomes a module ("external module" pre-TypeScript 1.5). This means that when the import * as diff from 'diff'; is present, things declared in index.ts become local only and don't consider/merge into the global namespace.

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

TypeScript spec, section 11.1: ...source files that contain at least one external import declaration, export assignment, or top-level exported declaration are considered separate external modules. Entities declared in an external module are in scope only in that module, but exported entities can be imported into other modules using import declarations

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

When you're not using external modules, TypeScript allows namespaces in different files to build upon each other. Once you start using external modules, this is no longer the case without using workarounds. In this case, it's often best to just switch to using external modules - if you're making a Node project, this is particularly easy because you don't have to worry about bundling.

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

Instead of a "deep namespace" (e.g. fgtApp.category.thing) like C# and .NET encourage - start thinking about each TypeScript source file as its own module. If you really do want a hierarchy, implement one with a folder structure.

即使 noImplicitAny 处于活动状态,此代码也会按您的预期工作:

This code will work as you expect even with noImplicitAny active:

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);

这篇关于为什么导入节点模块会破坏 atom-typescript 中的内部 Typescript 命名空间?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆