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

如何让函数参数推断Record类型中多对象字段的精确类型

问题:推断Record类型中对象字段的精确类型

我想要实现一个函数,使其能够推断传入Record类型中对象字段的精确类型。示例代码如下:

const exact = func({ foo: { a: 1, b: 2 } })
const _a: 1 = exact.foo.a
const _b: 2 = exact.foo.b // FIXME: typeof b 为`number`,而非`2`

目前我已实现让1被正确推断,但无法推断2,请问该如何解决?

我目前的代码尝试:

type FIXME = number

interface Thing<a extends number, b extends number> {
  a: a
  b: b
}

// prettier-ignore
const x = <_ extends Record<keyof _, number>>(args: {[k in keyof _]: Thing<_[k],FIXME>}): {[k in keyof _]: Thing<_[k],FIXME>} => args

解决方案

你当前的问题在于用固定的FIXME = number约束了b的类型,导致TypeScript无法捕获其字面量类型。要让所有字段的精确类型被推断,需要让泛型完整捕获传入对象的结构,而非硬编码类型约束。

方案1:基于预定义Thing类型的实现

interface Thing<A extends number, B extends number> {
  a: A;
  b: B;
}

// 让泛型T直接匹配传入的对象结构,保留所有字面量类型信息
const func = <T extends Record<string, Thing<number, number>>>(args: T): T => args;

// 测试验证
const exact = func({ foo: { a: 1, b: 2 } });
const _a: 1 = exact.foo.a; // 类型推断正确
const _b: 2 = exact.foo.b; // 现在类型为字面量2,而非宽泛的number

方案2:更通用的任意嵌套对象推断

如果不需要固定的Thing结构,希望支持任意嵌套对象的字面量类型推断,可以使用更灵活的写法:

const func = <T extends Record<string, Record<string, number>>>(args: T): T => args;

// 测试验证
const exact = func({ foo: { a: 1, b: 2 }, bar: { c: 3, d: 4 } });
const _a: 1 = exact.foo.a;
const _b: 2 = exact.foo.b;
const _c: 3 = exact.bar.c;
const _d: 4 = exact.bar.d;

原理说明

通过让泛型T直接捕获传入对象的完整结构,并且返回类型直接复用T,TypeScript会自动保留每个字段的字面量类型,而不会将其拓宽为number这类基础类型。

内容的提问来源于stack exchange,提问作者Jason Kuhrt

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 20:13:12