メインコンテンツへスキップ

no-shadow

外側のスコープで宣言された変数と同じ名前で変数を宣言することを禁止します。

このルールは、ベースとなるeslint/no-shadowルールを拡張したものです。TypeScriptのthisパラメータとグローバル拡張のサポートを追加し、TypeScriptの機能に関するオプションを追加します。

使い方

.eslintrc.cjs
module.exports = {
"rules": {
// Note: you must disable the base rule as it can report incorrect errors
"no-shadow": "off",
"@typescript-eslint/no-shadow": "error"
}
};

プレイグラウンドでこのルールを試す ↗

オプション

eslint/no-shadowのオプションを参照してください。

このルールには、以下のオプションが追加されています。

interface Options extends BaseNoShadowOptions {
ignoreTypeValueShadow?: boolean;
ignoreFunctionTypeParameterNameValueShadow?: boolean;
}

const defaultOptions: Options = {
...baseNoShadowDefaultOptions,
ignoreTypeValueShadow: true,
ignoreFunctionTypeParameterNameValueShadow: true,
};

ignoreTypeValueShadow

trueに設定すると、型に変数と同じ名前を付ける場合、このルールは無視します。一般的に、型のある場所ではtypeof演算子なしに変数を使用することはできないため、混乱のリスクはほとんどなく、安全です。

{ ignoreTypeValueShadow: true }が設定された場合の、正しいコードの例

type Foo = number;
interface Bar {
prop: number;
}

function f() {
const Foo = 1;
const Bar = 'test';
}
プレイグラウンドで開く
注意

シャドーイングとは、異なる、入れ子になったスコープにある2つの同一の識別子を指します。これは、同じスコープにある2つの同一の識別子の場合である再宣言とは異なります。再宣言は、代わりにno-redeclareルールによってカバーされます。

ignoreFunctionTypeParameterNameValueShadow

trueに設定すると、関数型内のパラメータに変​​数と同じ名前を付ける場合、このルールは無視します。

関数型の各引数は、関数型のスコープ内に値変数を作成します。これは、後でtypeof演算子を使用して型を参照できるようにするためです。

type Func = (test: string) => typeof test;

declare const fn: Func;
const result = fn('str'); // typeof result === string

これは、関数型の引数が、親スコープの値変数名をシャドーイングすることを意味します。

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演算子を使用しない場合は、このオプションを安全にオンにすることができます。

{ ignoreFunctionTypeParameterNameValueShadow: true }が設定された場合の、正しいコードの例

const test = 1;
type Func = (test: string) => typeof test;
プレイグラウンドで開く

FAQ

親スコープの変数と同じ名前を共有するenumメンバーについてルールが報告するのはなぜですか?

このケースの報告はバグではありません。これは完全に意図的で正しい報告です!enumの比較的知られていない機能のためにルールが報告します。enumメンバーはenumスコープ内に変数を作成するため、修飾子なしでenum内で参照できます。

例を用いて説明します。

const A = 2;
enum Test {
A = 1,
B = A,
}

console.log(Test.B);
// what should be logged?

上記のコードをナイーブに見ると、外部変数Aの値が2であるため、ログは2を出力するはずのように見えるかもしれません。しかし、代わりに1が出力されます。これはTest.Aの値です。これは、修飾されていないコードB = Aが、完全修飾コードB = Test.Aと同等であるためです。この動作のため、enumメンバーは外部変数の宣言をシャドーイングしました。

参考資料

ESLint coreから❤️を込めて採用しました。