基于本文回答

播面 播面

刷题像听歌,多听自然懂
0
评论

typeof 关键字在 TypeScript 类型上下文中的作用

知识点图片

在 TypeScript 中,typeof 关键字具有双重身份,它的作用取决于它所处的上下文

  1. JavaScript 运行上下文(Value Context): 也就是标准的 JS typeof,用于在运行时判断变量的数据类型(返回 'string', 'number', 'object' 等字符串)。
  2. TypeScript 类型上下文(Type Context): 这是 TS 特有的功能。当用在类型定义(如 type, interface, 泛型参数)中时,它的作用是捕获变量或属性的静态类型

以下详细解释 typeofTypeScript 类型上下文 中的核心作用和常见使用场景。


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;

进阶:配合 ReturnTypeParameters

通常我们不直接用 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 类型定义中的最佳实践:

  1. 减少样板代码: 从常量配置对象反向生成类型。
  2. 类型安全: 结合 keyof typeof 确保字符串参数必须是对象中存在的键。
  3. 工具类型: 结合 ReturnType<typeof func> 自动获取复杂函数的返回结构。
00:00
00:00