no-extraneous-class
不允許視為命名空間的類別。
擴充 "plugin:@typescript-eslint/嚴格"
在一個 ESLint 設定檔中 啟用這項規則。
此規則會報告當一個類別沒有非靜態成員時,例如專門作為靜態命名空間的類別。
從 物件導向程式 思維來的使用者可能會將他們的工具函式包覆在一個額外的類別中,而不是將它們放在 ECMAScript 模組的最上層。在 JavaScript 和 TypeScript 專案中,通常沒有必要這麼做。
- 包覆類別會在沒有增加任何結構性改善的情況下,增加額外的認知複雜度到程式碼中
- 無論是要放置哪些內容在其中,例如工具函式,按照模組中的順序組織已經足夠了。
- 作為替代方案,您可以使用
import * as ...
匯入所有模組到一個物件中。
- 當您開始輸入屬性名稱時,IDE 無法為靜態類別或命名空間匯入的屬性提供建議
- 當這些變數等皆在類別之中時,透過靜態分析程式碼以找出未使用的變數會較為困難(請參閱:尋找 TypeScript 中的未用程式碼(和未用類型))。
這條規則也會回報只有建構函式而沒有屬性的類別。這些類別通常可以用一個獨立的函式取代。
module.exports = {
"rules": {
"@typescript-eslint/no-extraneous-class": "error"
}
};
在操場嘗試這條規則 ↗
範例
- ❌ 錯誤
- ✅ 正確
class StaticConstants {
static readonly version = 42;
static isProduction() {
return process.env.NODE_ENV === 'production';
}
}
class HelloWorldLogger {
constructor() {
console.log('Hello, world!');
}
}
在操場打開export const version = 42;
export function isProduction() {
return process.env.NODE_ENV === 'production';
}
function logHelloWorld() {
console.log('Hello, world!');
}
在操場打開其他選項
個別匯出(建議)
我們建議,您個別地從您的模組匯出公用程式,而非使用一個靜態公用程式類別。
- ❌ 錯誤
- ✅ 正確
名稱空間匯入(不建議)
如果您強烈偏好於將來自模組的所有建構保存為單一物件的屬性,您可以import * as
該模組。這被稱為「名稱空間匯入」。名稱空間匯入有時較受青睞,這是因為它們會將所有屬性保留在巢狀之中,且當您開始或停止使用模組中的各種屬性時,不必進行變更。
然而,名稱空間匯入會受到這些缺點影響
- 它們在現代的打包器中也不太能進行 tree shaking
- 它們需要在每個屬性使用之前加上名稱前綴
- ❌ 錯誤
- ⚠️ 名稱空間匯入
- ✅ 獨立匯入
// utilities.ts
export class Utilities {
static sayHello() {
console.log('Hello, world!');
}
}
// consumers.ts
import { Utilities } from './utilities';
Utilities.sayHello();
在操場打開// utilities.ts
export function sayHello() {
console.log('Hello, world!');
}
// consumers.ts
import * as utilities from './utilities';
utilities.sayHello();
在操場打開// utilities.ts
export function sayHello() {
console.log('Hello, world!');
}
// consumers.ts
import { sayHello } from './utilities';
sayHello();
在操場打開變異變數的注意事項
您需要注意的一種情況是匯出可變異的變數。雖然類別屬性可以在外部進行變異,但已匯出的變數總是常數。這表示匯入者只能讀取分配給它們的第一個值,而且無法寫入這些變數。
需要寫入已匯出的變數的情況非常少見,而且通常會被視為程式碼警訊。如果您確實需要這麼做,您可以使用 getter 和 setter 函式來達成
- ❌ 錯誤
- ✅ 正確
選項
這條規則接受下列選項
type Options = [
{
/** Whether to allow extraneous classes that contain only a constructor. */
allowConstructorOnly?: boolean;
/** Whether to allow extraneous classes that have no body (i.e. are empty). */
allowEmpty?: boolean;
/** Whether to allow extraneous classes that only contain static members. */
allowStaticOnly?: boolean;
/** Whether to allow extraneous classes that include a decorator. */
allowWithDecorator?: boolean;
},
];
const defaultOptions: Options = [
{
allowConstructorOnly: false,
allowEmpty: false,
allowStaticOnly: false,
allowWithDecorator: false,
},
];
這條規則通常會禁止空的類別(沒有建構函式或屬性)。這條規則的各項選項都會針對特定類型的類別加入例外。
allowconstructoronly
allowConstructorOnly
新增一個對只有建構式而沒有欄位的類別豁免。
- ❌ 錯誤
- ✅ 正確
allowEmpty
allowEmpty
選項新增一個對完全空的類別豁免。
- ❌ 錯誤
- ✅ 正確
allowStaticOnly
allowStaticOnly
選項新增一個對只含有靜態成員的類別豁免。
我們強烈建議不要使用 allowStaticOnly
豁免。它違反了此規則的初衷,即不鼓勵只用於靜態成員的類別。
allowWithDecorator
allowWithDecorator
選項新增一個對已使用 @
裝飾子裝飾的類別豁免。
- ❌ 錯誤
- ✅ 正確
何時不使用它
如果您的專案是在建構類別和命名空間的時新作法之前設定的,而且您沒有時間轉換,則可能無法實際使用此規則。您可以考慮使用 ESLint disable 註解 取代完全停用此規則。