TypeScript:传递对象字面量作为参数时如何避免类型拓宽?
在最新TypeScript版本中,能否避免对象字面量参数的类型拓宽且无需使用
as const? 问题说明
希望在最新TypeScript版本中,实现将对象字面量作为函数参数传递时,自动保留属性值的字面量类型(避免被拓宽为string),同时调用函数时不需要额外添加as const断言。具体要求是该实现需支持所有扩展Record<string, string>的对象字面量。
当前实现代码
function func<T>(value: T): T { return value; }; let test = func({ key: 'value' }) // 类型推断结果:{ key: string;}
期望效果
// 改写func的声明后 let test = func({ key: 'value' }) // 类型推断结果:{ key: "value"; }
现有可行但不符合需求的方式
以下两种写法能达到期望的类型推断效果,但需要修改函数调用方式,不符合需求:
function func<T>(value: T): T { return value }; let test = func({ key: 'value' as const }) // 类型推断为 { key: "value"; } let test = func({ key: 'value' } as const ) // 类型推断为 { readonly key: "value"; }
解决方案
方案1:兼容旧版本的映射类型实现
通过自定义映射类型,将对象的字符串属性值强制转为字面量类型,同时约束输入类型为Record<string, string>的子类型:
type Literalize<T extends Record<string, string>> = { [K in keyof T]: T[K] extends string ? `${T[K]}` : T[K]; }; function func<T extends Record<string, string>>(value: Literalize<T>): Literalize<T> { return value; } let test = func({ key: 'value' }); // 类型推断结果:{ key: "value"; }
方案2:TypeScript 5.0+的const泛型参数(推荐)
TypeScript 5.0及以上版本支持const修饰泛型参数,直接让TypeScript对传入的对象字面量进行窄化推断,保留原始字面量类型:
function func<const T extends Record<string, string>>(value: T): T { return value; } let test = func({ key: 'value' }); // 类型推断结果:{ key: "value"; }
该方案无需额外定义类型,代码更简洁,但要求TypeScript版本≥5.0。
内容的提问来源于Stack Exchange,提问作者dsalex1
相关产品推荐
相关产品推荐

