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

TypeScript中Object.values()无法从Record联合类型推导正确类型怎么办?

TypeScript中Object.values()从Record联合类型推导正确类型的解决方案

问题场景

当使用Object.values()处理Record类型的联合时,TypeScript无法自动推导出正确的数组类型:

type A = Record<string, number>;
type B = Record<string, boolean>;

function func(value: A | B) {
    const properties = Object.values(value); // 实际类型为any[],期望是number[] | boolean[]
}

解决方案

1. 使用类型守卫区分联合类型

通过自定义类型守卫明确判断输入类型,让TypeScript能正确推导Object.values()的返回值:

type A = Record<string, number>;
type B = Record<string, boolean>;

// 类型守卫:判断是否为A类型
function isA(value: A | B): value is A {
    // 处理空对象情况,若需兼容空对象可额外添加判断逻辑
    const firstValue = Object.values(value)[0];
    return typeof firstValue === 'number';
}

function func(value: A | B) {
    let properties: number[] | boolean[];
    if (isA(value)) {
        properties = Object.values(value); // 类型为number[]
    } else {
        properties = Object.values(value); // 类型为boolean[]
    }
}

2. 自定义泛型工具函数

封装泛型函数,利用类型推断直接返回对应类型的数组:

type A = Record<string, number>;
type B = Record<string, boolean>;

// 泛型函数:提取Record的值类型组成数组
function getValues<T extends Record<string, infer U>>(obj: T): U[] {
    return Object.values(obj) as U[];
}

function func(value: A | B) {
    const properties = getValues(value); // 类型为number[] | boolean[]
}

3. 扩展Object.values的全局类型定义

通过全局声明扩展Object.values的类型,使其支持联合Record类型的推导:

declare global {
    interface ObjectConstructor {
        values<T extends Record<string, unknown>>(obj: T): T[keyof T][];
    }
}

type A = Record<string, number>;
type B = Record<string, boolean>;

function func(value: A | B) {
    const properties = Object.values(value); // 类型为number[] | boolean[]
}

方案说明

  • 类型守卫方案适合需要明确分支逻辑的场景,但需注意空对象等边界情况的处理;
  • 泛型工具函数方案简洁,仅在局部生效,不会影响全局类型;
  • 全局类型扩展方案会改变项目中所有Object.values的类型推断行为,需根据项目实际情况谨慎使用。

内容的提问来源于stack exchange,提问作者Serhii Holinei

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 19:03:27