如何根据可选对象参数动态变更TypeScript函数返回类型
问题描述
需要实现:当传入的obj参数中存在aX属性时,返回类型才包含{a: boolean};同理bX对应b、cX对应c。但当前代码中,调用func传入仅含aX的参数后,访问test1.b不会触发TypeScript错误,不符合预期,需让返回类型随输入参数动态调整。
当前代码:
type IObjFunc = () => void interface IObj { aX?: IObjFunc bX?: IObjFunc cX?: IObjFunc } interface IReturnData { a?: boolean b?: boolean c?: boolean } const func = (obj: IObj) => { const returnData: IReturnData = {} if (obj.aX) returnData.a = true if (obj.bX) returnData.b = true if (obj.cX) returnData.c = true return returnData } const test1 = func({ aX: () => undefined }) console.log(test1.a) // 正常 console.log(test1.b) // 未报错,但应该报错
解决方案
通过泛型结合映射类型实现动态返回类型,让输出严格匹配输入的属性映射关系:
type IObjFunc = () => void // 约束输入参数只能包含aX/bX/cX这些可选属性 type InputObj = Partial<{ aX: IObjFunc; bX: IObjFunc; cX: IObjFunc }> // 映射输入属性到输出属性的工具类型:把aX转为a,bX转为b,仅保留输入中存在的属性 type ReturnTypeFromInput<T extends InputObj> = { [K in keyof T as K extends `${infer P}X` ? P : never]: boolean } const func = <T extends InputObj>(obj: T): ReturnTypeFromInput<T> => { const returnData = {} as ReturnTypeFromInput<T> if ('aX' in obj && obj.aX) { (returnData as any).a = true } if ('bX' in obj && obj.bX) { (returnData as any).b = true } if ('cX' in obj && obj.cX) { (returnData as any).c = true } return returnData } // 测试验证 const test1 = func({ aX: () => undefined }) console.log(test1.a) // 正常 console.log(test1.b) // 触发TypeScript错误,符合预期 const test2 = func({ bX: () => undefined, cX: () => undefined }) console.log(test2.b) // 正常 console.log(test2.c) // 正常 console.log(test2.a) // 触发TypeScript错误
代码说明
- 泛型约束:
T extends InputObj确保输入参数只能包含指定的aX/bX/cX属性,避免非法输入。 - 映射类型:
ReturnTypeFromInput<T>利用模板字符串类型,自动将输入中的aX映射为输出的a,仅保留输入中实际存在的属性对应的输出键。 - 类型断言:函数内部赋值时用
as any临时绕过类型检查,因为TypeScript无法自动推断动态属性的赋值逻辑,实际运行逻辑是安全的。
修改后,返回类型会严格跟随输入参数的属性变化,访问不存在的输出属性时会立即触发TypeScript错误,完全符合需求。
内容的提问来源于stack exchange,提问作者kennarddh
相关产品推荐
相关产品推荐

