TypeScript如何定义值类型统一且保留键信息的对象?
解决方案:兼顾键名保留与自动类型推断
问题回顾
我定义了一个以Context对象作为第一个参数的Helper函数类型:
type Helper = (ctx: Context, ...params: any[]) => any;
想创建一个所有值均为Helper类型的对象,但现有方案要么丢失键名信息,要么需要重复标注ctx类型:
const lib = { path: (ctx) => ctx.getPath(), array: (ctx, ...params) => new MyArray(ctx, params), };
可行方案
方案1:泛型辅助函数(推荐)
通过泛型函数约束对象属性类型的同时,保留原对象的键名信息:
type Helper = (ctx: Context, ...params: any[]) => any; function createLib<T extends Record<keyof T, Helper>>(lib: T): T { return lib; } const lib = createLib({ path: (ctx) => ctx.getPath(), // ctx自动推断为Context类型 array: (ctx, ...params) => new MyArray(ctx, params), // 无需手动标注ctx类型 });
- 核心效果:既确保所有函数符合
Helper类型规范,又保留path、array等键名的类型推导,IDE可正常补全属性 - 最终类型:
lib的类型被推导为{ path: Helper; array: Helper }
方案2:satisfies关键字断言(简洁版)
利用TypeScript 4.9+的satisfies关键字,在不改变原对象类型推导的前提下,验证属性类型:
type Helper = (ctx: Context, ...params: any[]) => any; const lib = { path: (ctx) => ctx.getPath(), array: (ctx, ...params) => new MyArray(ctx, params), } as const satisfies Record<keyof typeof lib, Helper>;
- 核心效果:无需额外辅助函数,直接通过断言完成类型检查,同时完整保留键名信息
- 注意:
as const用于锁定对象的键名和函数类型,避免类型被宽泛化
核心优势
两种方案均实现了:
- 自动推断每个函数的
ctx参数为Context类型,无需重复标注 - 保留对象的所有键名信息,不会丢失属性的类型提示
- 严格约束所有函数符合
Helper类型定义,提供编译期类型检查
内容的提问来源于stack exchange,提问作者Prutser
相关产品推荐
相关产品推荐

