ES2015模块语法比自定义的TypeScript模块和命名空间更受欢迎。@typescript-eslint/no-namespace

66

我运行npm start时收到以下错误:

@ typescript-eslint / no-namespace:自定义TypeScript模块和命名空间不如ES2015模块语法更佳

    namespace InternalThings {...}

我试图研究这个问题,但是非常令人困惑。

为什么会出现这种情况? 该如何解决?

我尝试在我的tsconfig.json上添加一些标志,但到目前为止没有成功;

4个回答

73

这是一个lint错误,由于这个lint规则导致:https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-namespace.md

如果您发现该规则有用并想保留它,则需要修改您的代码以使用importexport替代命名空间。请参阅规则文档以了解什么算作修复。

如果您喜欢该规则,但想禁用此行的规则,请在其上方添加以下内容:

// eslint-disable-next-line @typescript-eslint/no-namespace
如果您不喜欢这个规则并希望完全禁用它,则可以编辑您的 .eslintrc 文件,并添加以下行:

如果您不喜欢这个规则并想要完全禁用它,那么请编辑您的 .eslintrc 文件,加入以下这一行:

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

4
你能提供你从文档中看到的修复方法吗? - Sasha Kondrashov
6
忽略规则并不是最好的解决方案。通过正确的导入修复它。 - Beta-Logics

51
要修复此错误,请改为:
export namespace InternalThings {
    export function myFunction() {
    }

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

InternalThings.myFunction();

你直接暴露了命名空间的所有成员:

export function myFunction() {
}

export class MyClass {
}

你可以像这样导入它:

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

InternalThings.myFunction();
你的模块的主要思想是,用户可以根据需要导入所需的内容,或者给你的模块取一个不同的名称:

主要思想是,模块使用者可以根据需要导入所需的内容,或使用不同的模块名称:

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

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

let field = new MyClass();

11

修复Lint错误时保持相同API

如果您想处理Lint错误而不破坏任何当前实现,可以执行以下操作,但在承诺执行此操作之前,您应该确实查看上面的答案:https://dev59.com/elMH5IYBdhLWcg3wyy3F#63574739

之前

实施

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

消费者

import { Container } from './Container'

Container.someCall()
Container.anotherCall()

之后

选项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,
}

方案二

您还可以将函数调用定义并封装到对象中,如下所示:

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

总结

如果你有一个庞大的代码库,并想要“快速”使你的代码符合linter规范,可以像上面那样进行重构。请确保考虑本回答中提到的https://dev59.com/elMH5IYBdhLWcg3wyy3F#63574739和其中的原因。

归根结底,最快的修复方法是关闭这个linting规则,正如本回答所述:https://dev59.com/elMH5IYBdhLWcg3wyy3F#58271234

如果你从头开始并遇到了此问题,我建议使用现代实现作为linter提示,但你可能会发现你也想要命名空间。如果你是团队的一部分,你可能需要先得到他们的反馈并遵循团队的标准。


边缘情况与注意事项

我遇到的一个情况是在同一个文件中有多个命名空间。在这种情况下,删除命名空间后可能会出现名称冲突。

示例

之前的代码

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

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

处理重命名冲突

在移除命名空间时

在这种情况下,当您移除命名空间并保留导出时,可以通过重命名冲突来解决:

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

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

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

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

另一种选择是将它们拆分成单独的文件。但如果您想要保持原始文件的导出,那么您需要导入并公开它们,这可能看起来重复,但可能是向更大的重构迈出的中间步骤(稍后更新导入以指向新文件)。这也允许您开始编写更现代的 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'

我们可以通过旧的原始模块代理新的 ESM 模块。

也许这需要一个新的问题 - 但是这是同样的错误,而且 - 我认为 - 你有答案:如何在这个命名空间中实现上述内容,避免命名冲突?声明全局 { 命名空间 Express { 导出接口 Request { reqId: string; } } } - undefined
@redevill 你可能想要提出一个更详细的问题。你想要保持它像这样:Express.Request?我不确定你是否可以在没有命名空间的情况下封装类型。除非Request是顶级导出的,然后你需要import * as Express from './myExpress'。我对你的命名冲突和你的确切目标有一些担忧。 - undefined
动力来自于接受了对 express.request 接口的扩展,参考链接:https://stackoverflow.com/a/47448486/452928。在实施时,您会遇到 OP 提到的代码检查错误。 - undefined
1
@redevill 由于你正在使用一个库,而且它的实现不在你的控制范围之内,最好在这种情况下使用忽略模式/规则/注释。 - undefined

2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接