如何在TypeScript中从配置对象推断处理函数的参数类型?
TypeScript命令解析工具的类型自动推断实现方案
这个需求完全可行,核心问题在于你原有的类型定义用了Record<string, Argument>,抹平了arguments的具体键名和每个参数的类型信息,导致TypeScript无法推断出handler参数的具体结构。关键实现点是用泛型捕获arguments的具体结构,再通过映射类型将参数类型映射为对应的TS类型。
具体实现步骤
- 定义类型映射表,将配置中的
type字符串映射为TypeScript原生类型:
type ArgTypeMap = { string: string; number: number; };
- 用泛型定义命令配置类型,绑定
arguments的具体结构,并自动推导handler的参数类型:
type CommandConfig<TArgs extends Record<string, { type: keyof ArgTypeMap }>> = { label: string; arguments: TArgs; // 映射arguments的每个键,将type转换为对应TS类型 handler: (options: { [K in keyof TArgs]: ArgTypeMap[TArgs[K]['type']] }) => void; };
- 用工厂函数创建命令,让TypeScript自动推断泛型参数(避免手动指定泛型的繁琐):
function createCommand<TArgs extends Record<string, { type: keyof ArgTypeMap }>>(config: CommandConfig<TArgs>) { return config; }
使用示例
const testCommand = createCommand({ label: 'test', arguments: { task_name: { type: 'string' }, count: { type: 'number' } }, handler: (options) => { // options会自动推断为 { task_name: string; count: number } console.log(options.task_name.toUpperCase()); // 类型安全,无报错 console.log(options.count.toFixed(2)); // 类型安全,无报错 } });
替代方案(若无法使用泛型)
- 类型断言:如果
arguments是动态生成的,可在handler中对options做类型断言,但会丢失部分类型安全:
handler: (options: unknown) => { const typedOptions = options as { task_name: string; count: number }; // 使用typedOptions }
- Schema验证库:引入
zod等库,通过定义schema同时实现运行时验证和类型推导,无需手动维护类型映射:
import { z } from 'zod'; const commandSchema = z.object({ label: z.string(), arguments: z.object({ task_name: z.object({ type: z.literal('string') }), count: z.object({ type: z.literal('number') }) }), handler: z.function().args(z.object({ task_name: z.string(), count: z.number() })).returns(z.void()) }); // 自动推导类型 type Command = z.infer<typeof commandSchema>;
内容的提问来源于stack exchange,提问作者Typestuck
相关产品推荐
相关产品推荐

