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

如何让含Readonly的可变参泛型函数保留字面量类型推断?

解决方案

要让可变参数函数保留传入对象字面量的键和值字面量类型,需要调整泛型约束的写法,避免TypeScript自动拓宽字面量类型为string。

问题根源

原写法中T extends Array<Readonly<Record<string, string>>>会让TypeScript将每个对象字面量的值自动拓宽为string类型,而非保留原始的字面量(比如"hello")。这是因为数组约束Array<X>会触发类型拓宽,将字面量类型提升到其基础类型。

正确声明方式

将泛型约束改为只读数组类型,让TypeScript对每个数组元素进行精确的字面量类型推断:

function foo2<T extends readonly Readonly<Record<string, string>>[]>(...args: T): void {
  // 函数逻辑
}

效果验证

调用该函数时,TypeScript会精确推断每个参数的完整字面量类型:

foo2({a: 'hello'}, {b: 'world'});
// T 被推断为:readonly [{ readonly a: "hello"; }, { readonly b: "world"; }]

原理说明

使用readonly ...[]作为泛型约束时,TypeScript会启用更严格的类型推断规则,不会将对象字面量的值自动拓宽为string,而是保留其原始的字面量类型。同时每个参数通过Readonly<Record<string, string>>约束确保是只读的键值对对象。

另一种可选写法

如果需要更灵活的类型检查,也可以用重载+条件类型的方式,确保每个参数符合要求的同时保留字面量:

// 类型推断用的重载签名
function foo2<T extends readonly any[]>(...args: T): T[number] extends Readonly<Record<string, string>> ? void : never;
// 实现签名
function foo2(...args: readonly Readonly<Record<string, string>>[]): void {
  // 函数逻辑
}

这种写法会在编译期检查每个参数是否符合Readonly<Record<string, string>>的约束,同时保留精确的字面量类型推断。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 09:02:47