如何基于嵌套类型的label筛选TypeScript对象的键类型
如何根据label筛选Payloads的键类型?
已知类型定义
type Payloads = { EventA: { label: 'Foo', content: object } EventB: { label: 'Bar', content: object } EventC: { label: 'Baz', content: object } } type SelectLabels = 'Foo' | 'Bar'
需求
需要创建类型TypeGoesHere,仅包含Payloads中值类型的label属于SelectLabels的键,使得调用函数时:
function f(x: TypeGoesHere) {} f('EventA') // 合法 f('EventB') // 合法 f('EventC') // 报错
尝试的错误代码及问题
尝试了以下代码:
type TypeGoesHere = Pick<keyof Payloads, Payloads[keyof Payloads]['label'][SelectLabels]>
但出现错误:
Property 'Bar' does not exist on type '"Foo" | "Bar" | "Baz"'.ts(2339) Property 'Foo' does not exist on type '"Foo" | "Bar" | "Baz"'.ts(2339)
正确实现方法
要实现这个需求,需要利用TypeScript的映射类型和条件类型筛选符合条件的键,以下是两种可行写法:
写法一:条件类型映射筛选
type TypeGoesHere = { [K in keyof Payloads]: Payloads[K]['label'] extends SelectLabels ? K : never }[keyof Payloads]
写法二:结合Extract工具类型
type TypeGoesHere = Extract<keyof Payloads, { [K in keyof Payloads]: Payloads[K]['label'] extends SelectLabels ? K : never }[keyof Payloads]>
原理说明
- 写法一中,先遍历
Payloads的所有键K,判断对应值的label是否属于SelectLabels:符合条件则保留键K,否则设为never。最后通过[keyof Payloads]索引访问,自动过滤掉never类型,得到目标联合类型"EventA" | "EventB"。 - 写法二则借助
Extract工具类型,从keyof Payloads中提取出符合条件的键,效果和写法一完全一致。
验证效果:
function f(x: TypeGoesHere) {} f('EventA') // ✅ 合法 f('EventB') // ✅ 合法 f('EventC') // ❌ 报错:类型'"EventC"'的参数不能赋给类型'"EventA" | "EventB"'的参数
内容的提问来源于stack exchange,提问作者Michael Moreno
相关产品推荐
相关产品推荐

