typeof 关键字在 TypeScript 类型上下文中的作用
在 TypeScript 中,typeof 关键字具有双重身份,它的作用取决于它所处的上下文:
- JavaScript 运行上下文(Value Context): 也就是标准的 JS
typeof,用于在运行时判断变量的数据类型(返回'string','number','object'等字符串)。 - TypeScript 类型上下文(Type Context): 这是 TS 特有的功能。当用在类型定义(如
type,interface, 泛型参数)中时,它的作用是捕获变量或属性的静态类型。
以下详细解释 typeof 在 TypeScript 类型上下文 中的核心作用和常见使用场景。
1. 核心作用:从值生成类型 (Type Inference)
最基本的作用是获取一个变量或对象的类型,而不需要手动编写类型定义。这对于保持“单一数据源(Single Source of Truth)”非常有用。
示例:基本变量
typescript
const age = 18;
// 在类型上下文中使用 typeof
type AgeType = typeof age;
// AgeType 推断为 number (或者 18,取决于是否是 const)
示例:对象 (非常常用)
当你有一个配置对象或常量对象,不想专门为它写一个 Interface 时:
typescript
const user = {
name: "Alice",
age: 30,
isAdmin: true
};
// 自动提取 user 对象的结构作为类型
type User = typeof user;
/*
User 的类型等同于:
{
name: string;
age: number;
isAdmin: boolean;
}
*/
// 使用该类型
const newUser: User = {
name: "Bob",
age: 25,
isAdmin: false
};
好处: 如果你修改了 user 对象(例如增加了一个字段),User 类型会自动更新,无需维护两份代码。
2. 配合 keyof 获取对象键的联合类型
这是 typeof 最常见的组合技:keyof typeof。用于获取一个对象所有 Key 组成的联合类型。
typescript
const colors = {
red: "#FF0000",
green: "#00FF00",
blue: "#0000FF"
};
// 1. typeof colors -> 获取对象的形状
// 2. keyof ... -> 获取该形状的所有键
type ColorKey = keyof typeof colors;
// ColorKey 等同于: "red" | "green" | "blue"
function getColor(key: ColorKey) {
return colors[key];
}
getColor("red"); // ✅ 合法
// getColor("yellow"); // ❌ 报错:类型“"yellow"”的参数不能赋给类型“"red" | "green" | "blue"”
3. 获取函数的类型
你可以捕获函数的签名(参数和返回值类型)。
typescript
function add(a: number, b: number): number {
return a + b;
}
type AddFunc = typeof add;
// AddFunc 等同于: (a: number, b: number) => number
const myAdd: AddFunc = (x, y) => x + y;
进阶:配合 ReturnType 和 Parameters
通常我们不直接用 typeof func 来定义另一个函数,而是配合工具类型提取函数的返回值或参数。
typescript
function createUser() {
return { id: 1, username: "admin", role: "super" };
}
// 提取返回值的类型
type UserData = ReturnType<typeof createUser>;
/*
UserData 等同于:
{
id: number;
username: string;
role: string;
}
*/
4. 处理类(Class)的构造函数类型
在 TypeScript 中,类(Class)既是类型(实例的类型),也是值(构造函数本身)。
- 直接使用
ClassName指的是实例的类型。 - 使用
typeof ClassName指的是构造函数(类本身)的类型。
typescript
class Dog {
bark() { console.log("Woof"); }
}
// 1. 使用类名作为类型 -> 指代实例
let myDog: Dog = new Dog();
// 2. 使用 typeof 类名 -> 指代构造函数本身(通常用于工厂模式)
function createInstance(Constructor: typeof Dog) {
return new Constructor();
}
createInstance(Dog);
5. 处理 Enum(枚举)
与类类似,Enum 在 TS 中也是一种特殊对象。
- 直接用
EnumName通常指代枚举成员的联合类型(在某些上下文中)。 typeof EnumName指代保存枚举映射关系的那个对象的类型。
typescript
enum Direction {
Up,
Down
}
// 指代枚举的值 (0 | 1)
let d: Direction = Direction.Up;
// 指代枚举对象本身 { Up: 0, Down: 1, "0": "Up", "1": "Down" }
type DirectionEnumObject = typeof Direction;
总结
| 上下文 | 代码示例 | 含义 |
|---|---|---|
| JavaScript (运行值) | console.log(typeof "abc") |
返回字符串 "string",用于运行时判断。 |
| TypeScript (类型) | type T = typeof varName |
获取变量 varName 的静态类型结构。 |
typeof 在 TS 类型定义中的最佳实践:
- 减少样板代码: 从常量配置对象反向生成类型。
- 类型安全: 结合
keyof typeof确保字符串参数必须是对象中存在的键。 - 工具类型: 结合
ReturnType<typeof func>自动获取复杂函数的返回结构。