You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何从对象动态推导TypeScript字符串联合类型?

从对象动态推导字符串联合类型的正确方法

没问题,我来帮你搞定这个类型推导的问题!你之前用Object.keys()的写法行不通,是因为TypeScript里Object.keys()的返回类型被设计成了string[](这是出于运行时安全性的考虑,避免遗漏继承来的对象属性),所以没法得到你想要的具体键名联合类型。

这里有两种完美符合你需求的实现方式:

方法一:从对象直接推导类型(推荐)

首先用as const断言你的对象,让TypeScript保留所有具体键名的字面量类型,然后通过keyof typeof获取联合类型:

// 用as const断言,让TS记住每个具体的键名
const goodKeys = { 
  'integer': 1, 
  'string': 1, 
  'number': 1, 
  'function': 1, 
  'boolean': 1, 
  'null': 1, 
  'undefined': 1, 
  'symbol': 1 
} as const;

// 直接从对象类型中提取键名的联合类型
export type OptsKey = keyof typeof goodKeys;

这样OptsKey就会被自动推导成你想要的:'integer' | 'string' | 'number' | 'function' | 'boolean' | 'null' | 'undefined' | 'symbol'

方法二:先定义类型再约束对象

如果你更倾向于先明确类型,再让对象符合这个类型,可以用Record工具类型来约束对象:

// 先定义目标联合类型
export type OptsKey = 'integer' | 'string' | 'number' | 'function' | 'boolean' | 'null' | 'undefined' | 'symbol';

// 用Record确保对象的键完全匹配OptsKey,值类型为1
const goodKeys: Record<OptsKey, 1> = { 
  'integer': 1, 
  'string': 1, 
  'number': 1, 
  'function': 1, 
  'boolean': 1, 
  'null': 1, 
  'undefined': 1, 
  'symbol': 1 
};

这种方式能保证对象和类型的一致性,后续修改类型时,TS会自动检查对象是否符合要求。

为什么你的原写法无效?

Object.keys(goodKeys)返回的是string[],TypeScript不会把它窄化成具体的键名数组,因为在JavaScript运行时,对象可能包含继承自原型链的额外属性,TS为了避免类型不安全,所以统一返回string[]。而keyof typeof是在编译时直接从对象的静态类型中提取键名,所以能得到精确的联合类型。

内容的提问来源于stack exchange,提问作者Alexander Mills

火山引擎 最新活动