no-shadow
Disallow variable declarations from shadowing variables declared in the outer scope.
This is an "extension" rule that replaces a core ESLint rule to work with TypeScript. See Rules > Extension Rules.
This rule extends the base no-shadow
rule from ESLint core. 它增加了对 TypeScript 的 this
参数和全局增强的支持,并增加了 TypeScript 功能的选项。
¥It adds support for TypeScript's this
parameters and global augmentation, and adds options for TypeScript features.
如何使用
- Flat Config
- Legacy Config
export default tseslint.config({
rules: {
// Note: you must disable the base rule as it can report incorrect errors
"no-shadow": "off",
"@typescript-eslint/no-shadow": "error"
}
});
module.exports = {
"rules": {
// Note: you must disable the base rule as it can report incorrect errors
"no-shadow": "off",
"@typescript-eslint/no-shadow": "error"
}
};
在线运行试试这个规则 ↗
选项
See eslint/no-shadow
's options.
¥Options
该规则添加了以下选项:
¥This rule adds the following options:
type AdditionalHoistOptionEntries = 'types' | 'functions-and-types';
type HoistOptionEntries =
| BaseNoShadowHoistOptionEntries
| AdditionalHoistOptionEntries;
interface Options extends BaseNoShadowOptions {
hoist?: HoistOptionEntries;
ignoreTypeValueShadow?: boolean;
ignoreFunctionTypeParameterNameValueShadow?: boolean;
}
const defaultOptions: Options = {
...baseNoShadowDefaultOptions,
hoist: 'functions-and-types',
ignoreTypeValueShadow: true,
ignoreFunctionTypeParameterNameValueShadow: true,
};
hoist:types
{ "hoist": "types" }
选项的错误代码示例:
¥Examples of incorrect code for the { "hoist": "types" }
option:
type Bar<Foo> = 1;
type Foo = 1;
Open in Playgroundhoist:functions-and-types
{ "hoist": "functions-and-types" }
选项的错误代码示例:
¥Examples of incorrect code for the { "hoist": "functions-and-types" }
option:
// types
type Bar<Foo> = 1;
type Foo = 1;
// functions
if (true) {
let b = 6;
}
function b() {}
Open in PlaygroundignoreTypeValueShadow
Whether to ignore types named the same as a variable. Default: true
.
这通常是安全的,因为你不能在没有 typeof
运算符的情况下在类型位置使用变量,因此混淆的风险很小。
¥This is generally safe because you cannot use variables in type locations without a typeof
operator, so there's little risk of confusion.
带有 { ignoreTypeValueShadow: true }
的正确代码示例:
¥Examples of correct code with { ignoreTypeValueShadow: true }
:
type Foo = number;
interface Bar {
prop: number;
}
function f() {
const Foo = 1;
const Bar = 'test';
}
Open in Playground遮蔽特指位于不同嵌套作用域中的两个相同标识符。这与重新声明不同,重新声明是两个相同的标识符位于同一范围内。重新声明由 no-redeclare
规则涵盖。
¥Shadowing specifically refers to two identical identifiers that are in different, nested scopes. This is different from redeclaration, which is when two identical identifiers are in the same scope. Redeclaration is covered by the no-redeclare
rule instead.
ignoreFunctionTypeParameterNameValueShadow
Whether to ignore function parameters named the same as a variable. Default: true
.
每个函数类型的参数都会在该函数类型的范围内创建一个值变量。这样做是为了你以后可以使用 typeof
运算符引用该类型:
¥Each of a function type's arguments creates a value variable within the scope of the function type. This is done so that you can reference the type later using the typeof
operator:
type Func = (test: string) => typeof test;
declare const fn: Func;
const result = fn('str'); // typeof result === string
这意味着函数类型参数影子值变量名称在父作用域中:
¥This means that function type arguments shadow value variable names in parent scopes:
let test = 1;
type TestType = typeof test; // === number
type Func = (test: string) => typeof test; // this "test" references the argument, not the variable
declare const fn: Func;
const result = fn('str'); // typeof result === string
如果你不在函数类型返回类型位置使用 typeof
运算符,则可以安全地启用此选项。
¥If you do not use the typeof
operator in a function type return type position, you can safely turn this option on.
带有 { ignoreFunctionTypeParameterNameValueShadow: true }
的正确代码示例:
¥Examples of correct code with { ignoreFunctionTypeParameterNameValueShadow: true }
:
const test = 1;
type Func = (test: string) => typeof test;
Open in Playground常见问题
¥FAQ
为什么规则报告与父作用域中的变量共享相同名称的枚举成员?
¥Why does the rule report on enum members that share the same name as a variable in a parent scope?
报告此案例不是错误 - 它是完全有意且正确的报告!规则报告由于枚举的一个相对未知的功能 - 枚举成员在枚举范围内创建一个变量,以便可以在枚举中引用它们而无需限定符。
¥Reporting on this case isn't a bug - it is completely intentional and correct reporting! The rule reports due to a relatively unknown feature of enums - enum members create a variable within the enum scope so that they can be referenced within the enum without a qualifier.
用一个例子来说明这一点:
¥To illustrate this with an example:
const A = 2;
enum Test {
A = 1,
B = A,
}
console.log(Test.B);
// what should be logged?
天真地看上面的代码,日志可能看起来应该输出 2
,因为外部变量 A
的值是 2
- 但是,代码会输出 1
,它是 Test.A
的值。这是因为非限定代码 B = A
相当于完全限定代码 B = Test.A
。由于这种行为,枚举成员已遮蔽外部变量声明。
¥Naively looking at the above code, it might look like the log should output 2
, because the outer variable A
's value is 2
- however, the code instead outputs 1
, which is the value of Test.A
. This is because the unqualified code B = A
is equivalent to the fully-qualified code B = Test.A
. Due to this behavior, the enum member has shadowed the outer variable declaration.
'## 资源'
Taken with ❤️ from ESLint core.