← 返回导航

ValueOf 与 KeyOf

工具类型 · 基础

场景说明

keyof T 是 TS 内置操作符,提取对象类型的所有键的联合类型。ValueOf<T> 不是内置的,但可以用一行工具类型实现:提取对象所有值的联合类型。两者配合使用可以构建类型安全的字典、枚举替代和配置映射。

完整代码


      
// keyof 与 ValueOf 的用法与对比

// 1. keyof T -- 提取对象所有键的联合类型
interface User {
  id: number;
  name: string;
  email: string;
}
type UserKey = keyof User;  // "id" | "name" | "email"

// 2. ValueOf<T> -- 提取对象所有值的联合类型(自定义工具类型)
type ValueOf<T> = T[keyof T];
type UserValue = ValueOf<User>;  // string | number

// 3. keyof 与 typeof 配合:从值推导类型
const config = {
  apiUrl: 'https://api.example.com',
  timeout: 5000,
  retry: 3,
} as const;
type ConfigKey = keyof typeof config;   // "apiUrl" | "timeout" | "retry"
type ConfigValue = typeof config[keyof typeof config];  // "https://api.example.com" | 5000 | 3

// 4. 实战:字典类型定义
const STATUS_MAP = {
  active: '激活',
  inactive: '未激活',
  banned: '封禁',
} as const;

type Status = keyof typeof STATUS_MAP;        // "active" | "inactive" | "banned"
type StatusLabel = typeof STATUS_MAP[Status];  // "激活" | "未激活" | "封禁"

// 5. 实战:枚举替代(更灵活)
const ROLES = {
  ADMIN: 1,
  USER: 2,
  GUEST: 3,
} as const;

type RoleName = keyof typeof ROLES;    // "ADMIN" | "USER" | "GUEST"
type RoleValue = typeof ROLES[RoleName];  // 1 | 2 | 3

// 6. 实战:配置映射类型安全
interface AppConfig {
  theme: 'light' | 'dark';
  lang: 'zh' | 'en';
  debug: boolean;
}
function getConfig<K extends keyof AppConfig>(key: K): AppConfig[K] {
  const config: AppConfig = { theme: 'light', lang: 'zh', debug: false };
  return config[key];
}
const theme = getConfig('theme');  // "light" | "dark"
const debug = getConfig('debug');  // boolean

关键点解析

使用示例与类型推导


      
// 实战:通过 ValueOf 构建类型安全的颜色映射

const COLORS = {
  primary: '#1890ff',
  success: '#52c41a',
  warning: '#faad14',
  error: '#f5222d',
} as const;

type ColorName = keyof typeof COLORS;     // "primary" | "success" | "warning" | "error"
type ColorHex = typeof COLORS[ColorName];  // "#1890ff" | "#52c41a" | "#faad14" | "#f5222d"

function useColor(name: ColorName): ColorHex {
  return COLORS[name];
}
const btnColor = useColor('primary');  // "#1890ff"
// useColor('unknown');  // 编译错误!

// 实战:类型安全的对象映射
function mapValues<T extends Record<string, unknown>>(
  obj: T
): ValueOf<T>[] {
  return Object.values(obj) as ValueOf<T>[];
}

const values = mapValues(COLORS);  // ColorHex[]
在 Playground 中尝试