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

问题描述 投票:0回答:5

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

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

    namespace InternalThings {...}

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

为什么会发生这种情况? 怎么解决?

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

javascript node.js reactjs typescript
5个回答
76
投票

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

如果您发现该规则有用并希望保留它,那么您需要修改代码以使用

import
export
而不是命名空间。请参阅该规则的文档,了解什么算作修复。

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

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

如果您不喜欢该规则并希望完全禁用它,请编辑 .eslintrc 文件以包含以下行:

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

52
投票

要修复此错误,请改为:

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

14
投票

在维护相同 API 的同时修复 Lint 错误

如果您想在不破坏任何当前实现的情况下处理 lint 错误,您可以执行以下操作,但在提交之前您应该真正查看上面的答案:https://stackoverflow.com/a/63574739/349659

之前

Implementation

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

Consumer

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

选项2

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

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

结论

如果你有一个很大的代码库并且想要“快速”安抚你的 linter,你可以像上面那样进行重构。请务必考虑这个答案https://stackoverflow.com/a/63574739/349659及其背后的推理。

最终,无需更改代码的最快修复方法是简单地关闭此答案中提到的此 linting 规则:https://stackoverflow.com/a/58271234/349659

如果您从头开始并遇到这个问题,我会考虑利用现代实现,如 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模块。


2
投票

错误来自 eslint。您必须忽略配置中的“@typescript-eslint/no-namespace”规则,或者使用 ES6 重写代码。

自定义 TypeScript 模块(module foo {})和命名空间(namespace foo {}) 被认为是过时的组织 TypeScript 代码的方法。 现在首选 ES2015 模块语法(导入/导出)

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


0
投票

在扩展“global”和“NodeJS”等全局命名空间以将环境变量添加到这些命名空间时,我遇到了类似的问题。

之前(有错误):

declare global {
    namespace NodeJS {
        interface ProcessEnv extends z.infer<typeof schema> {}
    }
}

之后:

declare module "global" {
  module "NodeJS" {
    interface ProcessEnv extends z.infer<typeof schema> {}
  }
}

希望这可以帮助有类似问题的人。

© www.soinside.com 2019 - 2024. All rights reserved.