在 TypeScript 中,類(class
)不僅是一個運行時的值(即可以實例化對象的構造函數),同時也是一個類型聲明。具體來說,類在 TypeScript 中既聲明了值,也聲明了類型,并且它的類型分為兩種:
- 實例化對象類型:描述通過
new
操作符創建的實例的結構。 - 類構造函數類型:描述類本身的結構(包括構造函數和靜態成員)。
1. 類聲明值
(1) 作為值
- 在運行時,類是一個普通的 JavaScript 構造函數。
- 它可以通過
new
關鍵字實例化對象。
示例
class User {name: string;constructor(name: string) {this.name = name;}greet(): void {console.log(`Hello, ${this.name}`);}
}// 使用類作為值
const user = new User("Alice");
user.greet(); // 輸出 "Hello, Alice"
在這里:
User
是一個構造函數,可以在運行時通過new
創建實例。
2. 類聲明類型
(1) 實例化對象類型
- 類本身也可以作為一個類型,用來描述通過
new
操作符創建的實例的結構。 - 這種類型被稱為實例化對象類型。
示例
class User {name: string;constructor(name: string) {this.name = name;}greet(): void {console.log(`Hello, ${this.name}`);}
}// 使用類作為類型
function printUser(user: User): void {console.log(user.name);
}const alice = new User("Alice");
printUser(alice); // 輸出 "Alice"
在這里:
User
被用作類型,表示alice
的類型是User
類的實例。
(2) 類構造函數類型
- 類本身也有一個類型,稱為類構造函數類型,它描述了類的靜態成員和構造函數簽名。
- 這種類型可以通過
typeof ClassName
獲取。
示例
class User {static defaultName: string = "Guest";name: string;constructor(name: string) {this.name = name;}greet(): void {console.log(`Hello, ${this.name}`);}
}// 使用類構造函數類型
function createUser(ctor: typeof User, name: string): User {return new ctor(name);
}const bob = createUser(User, "Bob");
bob.greet(); // 輸出 "Hello, Bob"console.log(User.defaultName); // 輸出 "Guest"
在這里:
typeof User
表示User
類的構造函數類型。createUser
函數接受一個類構造函數ctor
和一個名稱name
,并通過new ctor(name)
創建實例。
3. 實例化對象類型與類構造函數類型的區別
特性 | 實例化對象類型 | 類構造函數類型 |
---|---|---|
定義 | 描述通過 new 創建的實例的結構。 | 描述類本身的結構(包括靜態成員)。 |
獲取方式 | 直接使用類名(如 User )。 | 使用 typeof ClassName 。 |
用途 | 用于限制實例的結構。 | 用于限制類構造函數的結構。 |
示例 | const user: User = new User(); | const ctor: typeof User = User; |
4. 綜合示例
以下是一個綜合示例,展示了如何同時使用實例化對象類型和類構造函數類型。
示例代碼
class User {static defaultName: string = "Guest";name: string;constructor(name: string) {this.name = name || User.defaultName;}greet(): void {console.log(`Hello, ${this.name}`);}
}// 使用實例化對象類型
function printUser(user: User): void {console.log(user.name);
}// 使用類構造函數類型
function createUser(ctor: typeof User, name?: string): User {return new ctor(name);
}// 測試
const alice = new User("Alice");
printUser(alice); // 輸出 "Alice"const guest = createUser(User);
guest.greet(); // 輸出 "Hello, Guest"
在這里:
User
作為實例化對象類型,用于限制printUser
函數的參數類型。typeof User
作為類構造函數類型,用于限制createUser
函數的第一個參數類型。
5. 高級用法:泛型與類類型
結合泛型和類類型,可以實現更靈活的設計。
示例:工廠函數
class Point {x: number;y: number;constructor(x: number, y: number) {this.x = x;this.y = y;}
}function createInstance<T>(ctor: new (...args: any[]) => T, ...args: any[]): T {return new ctor(...args);
}const point = createInstance(Point, 10, 20);
console.log(point.x, point.y); // 輸出 10, 20
在這里:
createInstance
是一個通用的工廠函數,接受一個類構造函數和構造參數,返回類的實例。new (...args: any[]) => T
是類構造函數類型的泛型約束。
6. 總結
- 類聲明值:
- 類是一個運行時的構造函數,可以通過
new
創建實例。
- 類是一個運行時的構造函數,可以通過
- 類聲明類型:
- 實例化對象類型:描述類實例的結構。
- 類構造函數類型:描述類本身的結構(包括靜態成員和構造函數簽名)。
- 區別:
- 實例化對象類型關注實例的屬性和方法。
- 類構造函數類型關注類的靜態成員和構造函數。
- 應用場景:
- 實例化對象類型用于限制實例的類型。
- 類構造函數類型用于限制類的類型(如工廠函數)。