TypeScript中如何根据泛型可选参数对象定义返回值类型?
解决TypeScript中根据options动态生成函数参数类型的问题
你需要实现一个函数createFun,使其返回的函数接收的args对象仅包含options中提供的键对应的大写形式,未提供的键不会出现在args的类型中,访问未提供的键时TypeScript会报错。以下是优化后的实现方案:
const createFun = <T extends Partial<Record<'a' | 'b' | 'c', unknown>>>(options: T) => { // 将T的键转换为大写,生成仅包含已提供键的Args类型 type Args = { [K in keyof T as Uppercase<K & string>]: T[K] }; return (fun: (args: Args) => void) => { const args = {} as Args; // 遍历options,将键转为大写后赋值给args,保证运行时结构与类型一致 for (const key in options) { if (Object.prototype.hasOwnProperty.call(options, key)) { const upperKey = key.toUpperCase() as Uppercase<typeof key>; args[upperKey] = options[key]; } } fun(args); }; }; // 测试示例:仅传入a属性 createFun({ a: { one: 1, two: 2 } })(args => { console.log(args.A.one); // 正常编译执行,输出1 // console.log(args.B); // 编译报错:Property 'B' does not exist on type '{ A: { one: number; two: number; }; }' }); // 测试示例:传入a和c属性 createFun({ a: 123, c: true })(args => { console.log(args.A); // 123 console.log(args.C); // true // console.log(args.B); // 编译报错 });
关键改动说明
- 基于实际传入的options生成类型:改用单一泛型
T约束options,直接根据用户传入的属性集合动态生成Args类型,自然过滤未提供的键 - 映射类型+大写转换:通过
Uppercase工具类型将小写键转为大写,同时仅保留T中实际存在的键,避免生成冗余属性 - 运行时结构对齐:遍历
options动态生成args对象,保证运行时的对象结构与TypeScript类型完全匹配
原代码的问题
原代码通过三个独立泛型TA/TB/TC定义类型,无论用户是否传入对应属性,args都会强制包含A/B/C三个键(类型为never或unknown),无法实现“移除未提供键”的需求。
如果需要扩展更多键(比如d、e),只需修改Record<'a' | 'b' | 'c' | 'd', unknown>中的键列表即可,无需调整其他逻辑。
内容的提问来源于stack exchange,提问作者sgmonda
相关产品推荐
相关产品推荐

