简体   繁体   English

ES2015 模块语法优于自定义 TypeScript 模块和命名空间@typescript-eslint/no-namespace

[英]ES2015 module syntax is preferred over custom TypeScript modules and namespaces @typescript-eslint/no-namespace

I'm receiving the following error running npm start:我在运行 npm 启动时收到以下错误:

ES2015 module syntax is preferred over custom TypeScript modules and namespaces @typescript-eslint/no-namespace ES2015 模块语法优于自定义 TypeScript 模块和命名空间@typescript-eslint/no-namespace

    namespace InternalThings {...}

I tried to research this but it's very confusing.我试图研究这个,但它非常令人困惑。

Why does this is happening?为什么会这样? How to fix it?如何解决?

I tried to put some flags on my tsconfig.json but so far no success;我试图在我的 tsconfig.json 上放置一些标志,但到目前为止没有成功;

This is a lint error, caused by this lint rule: https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-namespace.md这是由以下 lint 规则引起的 lint 错误: https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-namespace.md

If you find the rule useful and want to keep it, then you'll need to modify your code to use import and export instead of namespace.如果您发现该规则有用并希望保留它,那么您需要修改您的代码以使用importexport而不是命名空间。 See the documentation of the rule for what counts as a fix.请参阅规则的文档,了解什么是修复。

If you like the rule, but want to disable the rule for this line, add the following just above it:如果您喜欢该规则,但想禁用该行的规则,请在其上方添加以下内容:

// eslint-disable-next-line @typescript-eslint/no-namespace

If you don't like the rule and want to disable it entirely, then edit your.eslintrc file to have the following line:如果您不喜欢该规则并想完全禁用它,请编辑您的 .eslintrc 文件以包含以下行:

rules: {
  "@typescript-eslint/no-namespace": "off"
}

To fix this error, instead of:要修复此错误,而不是:

export namespace InternalThings {
    export function myFunction() {
    }

    export class MyClass {
    }
}
import { InternalThings } from './internal-things';

InternalThings.myFunction();

you expose all the members of the namespace directly:您直接公开命名空间的所有成员:

export function myFunction() {
}

export class MyClass {
}

and you import it like this:你像这样导入它:

import * as InternalThings from './internal-things';

InternalThings.myFunction();

The main idea is that users of your module can import only what they want, or name your module differently:主要思想是您的模块的用户只能导入他们想要的内容,或者以不同的方式命名您的模块:

import * as CustomModuleName from './internal-things';

CustomModuleName.myFunction();
import { MyClass } from './internal-things';

let field = new MyClass();

The error is coming from eslint.错误来自 eslint。 You have to either ignore '@typescript-eslint/no-namespace' rule in the config or rewrite your code using ES6.你必须要么忽略配置中的“@typescript-eslint/no-namespace”规则,要么使用 ES6 重写你的代码。

Custom TypeScript modules (module foo {}) and namespaces (namespace foo {}) are considered outdated ways to organize TypeScript code.自定义 TypeScript 模块(模块 foo {})和命名空间(命名空间 foo {})被认为是组织 TypeScript 代码的过时方式。 ES2015 module syntax is now preferred (import/export)现在首选 ES2015 模块语法(导入/导出)

Refer https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-namespace.md参考https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-namespace.md

Fix Lint Error While Maintaining Same API修复 Lint 错误,同时保持相同 API

If you would like to handle the lint error without breaking any current implementations you can do the following, but you should really look at the above answer before committing to this: https://stackoverflow.com/a/63574739/349659如果您想在不破坏任何当前实现的情况下处理 lint 错误,您可以执行以下操作,但在提交之前您应该真正查看上述答案: https://stackoverflow.com/a/63574739/349659

Before

Implementation

export namespace Container {
  export function someCall() { }
  export function anotherCall() { }
}

Consumer

import { Container } from './Container'

Container.someCall()
Container.anotherCall()

After

Option 1选项1

// These are essentially private
function someCall() { }
function anotherCall() { }

// We expose them here
// This feels like a step towards CommonJS, but is valid ES Module code
export const Container = {
  someCall,
  anotherCall,
}

Option 2选项 2

You could also define and encapsulate the function calls directly into the object as well like so:您还可以将 function 调用直接定义并封装到 object 中,如下所示:

export const Container = {
  someCall() {},
  anotherCall() {},
}

In Conclusion综上所述

If you have a large codebase and want to "quickly" appease your linter, you can do a refactor like above.如果你有一个庞大的代码库并且想要“快速”安抚你的 linter,你可以像上面那样进行重构。 Make sure to consider this answer https://stackoverflow.com/a/63574739/349659 and the reasoning behind it.请务必考虑这个答案https://stackoverflow.com/a/63574739/349659及其背后的原因。

At the end of the day, the quickest fix that requires no code change is to simply turn off this linting rule as mentioned in this answer: https://stackoverflow.com/a/58271234/349659归根结底,不需要更改代码的最快修复方法是简单地关闭此 linting 规则,如此答案中所述: https://stackoverflow.com/a/58271234/349659

If you're starting from scratch and run into this issue I would consider utilizing the modern implementation as the linter hints towards, but you may find that you enjoy namespaces and simply want them as well.如果您从头开始并遇到这个问题,我会考虑使用现代实现作为 linter 提示,但您可能会发现您喜欢命名空间并且也只是想要它们。 If you're part of a team you may want to get their feedback first and and follow a team standard.如果您是团队的一员,您可能希望首先获得他们的反馈并遵循团队标准。


Edge Cases & Considerations边缘案例和注意事项

One case I've ran into is having multiple namespaces in the same file.我遇到的一种情况是在同一个文件中有多个命名空间。 In this scenario you may then have name collisions after removing the namespace.在这种情况下,您可能会在删除命名空间后发生名称冲突。

Example例子

Before

export namespace Container {
  export function someCall() { }
  export function anotherCall() { }
}

export namespace AnotherContainer {
  export function someCall() { }
  export function anotherCall() { }
}

After

Renaming Collisions重命名碰撞

In this scenario when you remove the namespace you can rename the collisions while maintaining the export like so:在这种情况下,当您删除命名空间时,您可以重命名冲突,同时保持导出,如下所示:

function containerSomeCall() { }
function containerAnotherCall() { }

export const Container = {
  someCall: containerSomeCall,
  anotherCall: containerAnotherCall,
}

function anotherContainerSomeCall() { }
function anotherContainerAnotherCall() { }

export const AnotherContainer = {
  someCall: anotherContainerSomeCall,
  anotherCall: anotherContainerAnotherCall,
}
Decoupling the Code解耦代码

Another option is to decouple them into their own files.另一种选择是将它们解耦到自己的文件中。 If you want to maintain the exports of the original file though you will need to import and expose them which may seem duplicate, but may be an intermittent step towards a larger refactoring (later updating imports to point at the new files).如果您想维护原始文件的导出,尽管您需要导入并公开它们,这可能看起来是重复的,但可能是朝着更大重构的间歇性步骤(稍后更新导入以指向新文件)。 This also allows you to start writing more modern ESM code too if you would like, while proxying new exports through the old module.如果您愿意,这也允许您开始编写更现代的 ESM 代码,同时通过旧模块代理新导出。

Container.ts

function someCall() { }
function anotherCall() { }

export const Container = {
  someCall,
  anotherCall,
}

AnotherContainer.ts

function someCall() { }
function anotherCall() { }

export const AnotherContainer = {
  someCall,
  anotherCall,
}

OriginalFile.ts

export * from './Container'
export * from './AnotherContainer'

We can proxy the new ESM modules through the old original module.我们可以通过旧的原始模块代理新的 ESM 模块。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM