如何让函数的返回值类型完全依赖于其参数类型?
如何让函数的返回值类型完全依赖于其参数类型?
嘿,我现在碰到这么个TypeScript的问题,先给你看看我手头的代码:
type TIn = { xa?: number; xb?: string; xc?: boolean; // ... 还有其他待扩展的字段 } type TOut = { ya: number | undefined; yb: string | undefined; yc: TPerson | undefined; // ... 对应输入的其他字段 } type TPerson = { name: string; age: number; } function fn(input: TIn): TOut { // 这里是函数的具体实现逻辑 }
我现在想实现的效果是:让返回值TOut里每个字段的静态空值检查,严格和输入TIn的对应字段绑定——说白了就是不想手动维护TOut的结构,让它完全跟着TIn的类型走,输入类型变了返回值类型自动同步更新,不用我每次改输入都要手动改输出类型。
作为常泡技术社区的老玩家,咱可以用TypeScript的映射类型来搞定这个需求,完全不用写死TOut的结构,让它自动从输入类型推导出来。下面给你两种实用的实现方式:
方式一:手动指定输入输出的键映射
如果输入和输出的键名没什么固定规律,比如xa对应ya、xb对应yb是自定义的对应关系,那可以先定义一个键映射类型,再自动生成返回值类型:
type TPerson = { name: string; age: number; } // 先把输入键和输出键的对应关系明确下来 type InToOutKeyMap = { xa: 'ya'; xb: 'yb'; xc: 'yc'; // 后续加新字段的话,直接在这里补充就行 } // 自动生成返回值类型:把输入的每个字段类型,对应到输出的键上,自动带上undefined type TOutFromIn<T extends Record<keyof InToOutKeyMap, any>> = { [K in keyof InToOutKeyMap as InToOutKeyMap[K]]: T[K] | undefined; } // 现在函数的返回值就完全由输入类型动态推导了 function fn<T extends { xa?: number; xb?: string; xc?: boolean; /* ... */ }>(input: T): TOutFromIn<T> { // 这里写你的业务逻辑,示例如下 return { ya: input.xa, yb: input.xb, yc: input.xc ? { name: '小明', age: 25 } : undefined, // 其他字段照着这个逻辑补充 } as TOutFromIn<T>; }
方式二:用模板字符串自动转换键名
如果你的输入和输出键名有固定规律(比如都是x开头转y开头,像xa→ya、xb→yb),那连键映射都不用手动写,用TypeScript的模板字符串类型就能自动转换:
type TPerson = { name: string; age: number; } // 自动把x开头的键转成y开头的键名 type XToYKey<K extends string> = K extends `x${infer Rest}` ? `y${Rest}` : never; // 生成返回值类型:自动映射键名,类型完全继承输入字段 type TOutFromIn<T> = { [K in keyof T as XToYKey<K>]: T[K] | undefined; } // 函数定义会更简洁 function fn<T extends { xa?: number; xb?: string; xc?: boolean; /* ... */ }>(input: T): TOutFromIn<T> { return { ya: input.xa, yb: input.xb, yc: input.xc ? { name: '小明', age: 25 } : undefined, } as TOutFromIn<T>; }
这么处理之后,不管你给输入类型加多少新字段,返回值类型都会自动同步更新,空值检查也会严格和输入保持一致——比如如果输入的xa改成必填的xa: number,那返回的ya就会是number | undefined(要是你想让必填输入对应必填返回,只需要调整映射类型里的定义就行),完全实现了返回值类型依赖参数类型的要求。
备注:内容来源于stack exchange,提问作者Mario Vernari
相关产品推荐
相关产品推荐

