Description
Overview
There are quite a few times when users have a real need to change or disable a rule for specifically some package exports:
- Enhancement:
@typescript-eslint/no-floating-promises
should Ignore node 18's built-in test function #5231: At least the new built-innode:test
runner intentionally returns ignorable Promises from itstest()
method that can be ignored by the rule - The
allowedNames
option fromexplicit-module-boundary-types
- The
typesToIgnore
option fromno-unnecessary-type-assertion
- The
allowedPromiseNames
option frompromise-function-async
- Proposed: [no-unnecessary-condition] ignore array index return #1798
- Proposed: feat(eslint-plugin): [prefer-readonly-parameter-types] added an optional type allowlist #4436
This RFC proposes a unified format that all rules can use to specify some types or values from the global namespace and/or packages.
Prior Art
Some rules have previously created name-based overrides, such as typesToIgnore
from no-unnecessary-type-assertion
. Those are sub-optimal:
- Names have conflicts. If you configure a rule for, say, all functions of a particular name that a package exports, you might also happen to ignore the rule for your internal functions of the same name.
- It may be necessary to configure a rule for all values of a particular type, regardless of their name.
For example, @typescript-eslint/no-floating-promises
even has a void
operator to get around needing to disable the rule for specific cases. It's the workaround we currently recommend for issues such as #5231.
Proposal
The current proposal is for specifying the following types of sources, in increasing order of distance from a line of code:
- File: the current file or another specific file in your package (often exported as a module, but not necessarily)
- Lib: globals such as from
lib.d.ts
orlib.dom.d.ts
- Package: an export from a package, such as
"lodash"
Additionally, you can specify multiple of these at the same time with type many.
interface FileSpecifier {
from: "file";
name: string | string[];
source?: string;
}
interface LibSpecifier {
from: "lib";
name: string | string[];
}
interface PackageSpecifier {
from: "package";
name: string | string[];
source: string;
}
interface ManySpecifiers {
from: EntitySpecifierFrom[];
name: string;
}
type EntitySpecifierFrom = "file" | "lib" | "package";
type EntitySpecifier =
| string
| FileSpecifier
| LibSpecifier
| PackageSpecifier
| ManySpecifiers;
An example of how this might look in practice:
export default {
rules: {
// https://github.com/typescript-eslint/typescript-eslint/issues/5231
"@typescript-eslint/no-floating-promises": ["error", {
"ignore": [
{
"from": "node:test",
"name": ["it", "test"]
}
]
}],
}
}
See #5271 (comment) and following comments for more context.
Original format, not rich enough
I propose the format look be able to specify whether the item is from the global namespace (i.e. globalThis
, window
) or a module (e.g. "node:test"
, "./path/to/file"
):
interface GlobalSpecifier {
name: string;
}
interface ModuleSpecifier {
export: string;
module: string;
}
type Specifier = GlobalSpecifier | ModuleSpecifier;
Examples
For example, specifying the global location
object:
{
"name": "location"
}
Instead specifying the global window.location
object:
{
"name": "window.location"
}
Specifying the test
export from the node:test
module:
{
"export": "test",
"module": "node:test"
}
Specify the SafePromise
export from some ~/utils/promises
module (presumably configured by TSConfig paths to point to a file with a location like ./src/utils/promises.ts
):
{
"export": "SafePromise",
"module": "~/utils/promises"
}
Specify the SafePromise
export from some my-safe-promises
(TODO: find some unused or useful name) module:
{
"export": "SafePromise",
"module": "safe-promises"
}