You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript:如何从多对象中按值类型获取所有属性键(非仅交集键)

问题描述

我有一个包含多个子对象(foo、bar、baz)的对象,这些子对象各自拥有不同数据类型的属性。我需要创建一个类型TValueObject,包含所有值类型为对象的属性键,即TValueObject应等于"clientId" | "apiKey" | "oauthToken" | "companyId",但目前仅得到所有对象的交集键"clientId"。

代码示例

源对象定义

const apiToken = {
  foo: {
    clientId: { enTitle: 'Client ID', value: '' },
    apiKey: { enTitle: 'Api Key', value: '' },
    enTitle: 'Foo',
    isOpen: false,
  },
  bar: {
    apiKey: { enTitle: 'Api Key', value: '' },
    clientId: { enTitle: 'Client ID', value: '' },
    enTitle: 'Bar',
    isOpen: false,
  },
  baz: {
    oauthToken: { enTitle: 'OAuth token', value: '' },
    companyId: { enTitle: 'Company ID', value: '' },
    clientId: { enTitle: 'Client ID', value: '' },
    enTitle: 'Baz',
    isOpen: false,
  },
};

按值类型筛选属性的映射类型

type PickByValue<T, ValueType> = Pick<
  T,
  {
    [Key in keyof T]-?: T[Key] extends ValueType ? Key : never;
  }[keyof T]
>;

当前不符合预期的类型定义

type TKey = keyof typeof apiToken;
type TValueObject = keyof PickByValue<typeof apiToken[TKey], object>;

问题原因

typeof apiToken[TKey]是foo、bar、baz三个子对象的联合类型。当对联合类型应用PickByValue时,TypeScript会对联合类型的每个成员分别处理,但keyof (A | B | C)最终会解析为三个子对象键的交集(即所有子对象共有的键),所以最终只得到了三个子对象都有的clientId。

解决方案

要获取所有子对象中值为对象类型的键的联合类型,需要通过分布式条件类型遍历每个子对象,分别筛选后再合并结果:

直接修改TValueObject定义

type TValueObject = keyof typeof apiToken extends infer K 
  ? K extends keyof typeof apiToken 
    ? keyof PickByValue<typeof apiToken[K], object> 
    : never 
  : never;

通用工具类型(可复用)

如果需要多次使用这种逻辑,可以封装成通用类型:

// 从对象的所有子对象中筛选值为指定类型的键的联合类型
type PickByValueFromUnion<T extends Record<string, any>, ValueType> = 
  keyof T extends infer K 
    ? K extends keyof T 
      ? keyof PickByValue<T[K], ValueType> 
      : never 
    : never;

// 使用通用类型定义TValueObject
type TValueObject = PickByValueFromUnion<typeof apiToken, object>;

此时TValueObject的类型会正确解析为:"clientId" | "apiKey" | "oauthToken" | "companyId"

内容的提问来源于stack exchange,提问作者Иннокентий Цетуев

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 11:05:17