Skip to content

noPrivateImports

¥Summary

¥How to configure

biome.json
{
"linter": {
"rules": {
"correctness": {
"noPrivateImports": "error"
}
}
}
}

¥Description

限制导入私有导出项。

¥Restrict imports of private exports.

在 JavaScript 和 TypeScript 中,一旦你使用 export 声明一个符号(例如类型、函数或任何其他可导出的内容),它就被视为公共的,可以从任何地方导入。遗憾的是,这使得强制执行模块边界变得困难,例如,难以阻止导入仅用于测试目的而导出的内容。

¥In JavaScript and TypeScript, as soon as you export a symbol, such as a type, function, or anything else that can be exported, it is considered public and can be imported from anywhere else. Unfortunately, this makes it hard to enforce module boundaries, or to prevent importing things that were only exported for test purposes, for instance.

此规则识别 JSDoc 标签 @public@package@private,以便你可以自由设置导出的可见性。未添加 <export> 标签的导出默认可见性为 public,但可以进行配置。

¥This rule recognizes the JSDoc tags @public, @package, and @private so that you are free to set the visibility of exports. Exports without tag have a default visibility of public, but this can be configured.

如果 @access 标签与 publicpackageprivate 值一起使用,则也受支持。

¥The @access tag is also supported if it’s used with one of the values public, package, or private.

¥Public visibility

默认设置为公开可见,这意味着导入给定符号没有任何限制。换句话说,如果没有这条规则,所有导出的符号都将隐式地公开。

¥Public visibility is the default and means there are no restrictions for importing a given symbol. In other words, without this rule, all exported symbols are implicitly public.

¥Package visibility

在此规则的上下文中,“包可见性”指的是符号在同一个 “package” 中可见,这意味着位于同一文件夹或其子文件夹中的任何模块都可以导入该符号。仅共享同一文件夹的模块不允许导入符号。

¥Within the context of this rule, package visibility means that a symbol is visible within the same “package”, which means that any module that resides in the same folder, or one of its subfolders, is allowed to import the symbol. Modules that only share a common folder higher up in the hierarchy are not allowed to import the symbol.

如需查看可视化说明,请参阅 此图

¥For a visual explanation, see this illustration.

¥Private visibility

私有可见性意味着符号不能从其他模块导入。

¥Private visibility means that a symbol may not be imported from other modules.

理解 @private 的关键在于,这条规则并没有将模块和文件视为同一事物。虽然文件确实是模块,但文件夹也被视为模块,其文件和子文件夹则是子模块。因此,从索引文件(例如 index.js)导出为 @private 的符号仍然可以从同一模块中的其他子模块导入。

¥The key thing to understanding the usefulness of @private is that this rule doesn’t treat modules and files as one and the same thing. While files are indeed modules, folders are considered modules too, with their files and subfolders being submodules. Therefore, symbols exported as @private from an index file, such as index.js, can still be imported from other submodules in that same module.

私有可见性仍然有用的另一个原因是,它允许你选择特定的例外情况。例如,使用 overrides 时,你可能需要在所有扩展名为 .test.js 的文件中禁用此规则。这样,标记为私有的符号将无法从外部模块导入,测试文件除外。

¥Another reason why private visibility may still be useful is that it allows you to choose specific exceptions. For example, using overrides, you may want to disable this rule in all files with a .test.js extension. This way, symbols marked private cannot be imported from outside modules, with the exception of test files.

¥Known Limitations

  • 此规则仅适用于从 JavaScript 和 TypeScript 文件导入的内容。无论默认可见性设置如何,图片或 CSS 文件等资源的导入都会被排除在外。

    ¥This rule only applies to imports from JavaScript and TypeScript files. Imports for resources such as images or CSS files are exempted regardless of the default visibility setting.

  • 此规则不验证通过动态 import() 表达式或 CommonJS require() 调用导入的内容。

    ¥This rule does not validate imports through dynamic import() expressions or CommonJS require() calls.

  • 来自 node_modules 下依赖的导入被视为超出范围。

    ¥Imports from dependencies under node_modules are considered out of scope.

¥Examples

¥Invalid

sub/foo.js
/**
* @package
*/
export const fooPackageVariable = 1;
bar.js
// Attempt to import package private variable from `sub/foo.js` from
// outside its `sub` module:
import { fooPackageVariable } from "./sub/foo.js";
/**
* @private For test purposes only!
*/
export function getTestStuff() {}
/bar.js:3:10 lint/correctness/noPrivateImports ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

You may not import a symbol with package visibility from here.

1 │ // Attempt to import package private variable from `sub/foo.js` from
2 │ // outside its `sub` module:
> 3 │ import { fooPackageVariable } from “./sub/foo.js”;
^^^^^^^^^^^^^^^^^^
4 │
5 │ /**

You may need to import an alternative symbol, or relax the visibility of this symbol.

This symbol was imported from /sub/foo.js.

bar.test.js
// Attempt to import a private export. To allow this, you probably want
// to configure an `override` to disable this rule in test files.
// See: https://biome.nodejs.cn/reference/configuration/#overrides
import { getTestStuff } from "./bar.js";
/bar.test.js:4:10 lint/correctness/noPrivateImports ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

You may not import a symbol with private visibility from here.

2 │ // to configure an `override` to disable this rule in test files.
3 │ // See: https://biome.nodejs.cn/reference/configuration/#overrides
> 4 │ import { getTestStuff } from “./bar.js”;
^^^^^^^^^^^^
5 │

You may need to import an alternative symbol, or relax the visibility of this symbol.

This symbol was imported from /bar.js.

¥Valid

sub/index.js
// Package-private exports can be imported from inside the same module.
import { fooPackageVariable } from "./foo.js";
// Resources (anything other than JS/TS files) are always exempt.
import { barResource } from "../resources/bar.png";
/** @private */
export const subPrivateVariable = 2;
sub/deep/index.js
// Private exports are accessible within the same module only, but
// modules can be nested. So the following works because you can always
// import from the index file of a parent module:
import { subPrivateVariable } from "../index.js";

¥Related links