如何让TypeScript根据传入的Props推断函数返回值类型
让TypeScript精准识别函数调用的返回类型
问题场景
现有如下TypeScript代码,函数myFunction仅接受param1或param2作为可选参数,但其返回值默认被推断为联合类型,无法精准识别result1这类特定参数对应的返回类型:
interface IMyFunctionWithParam1 { param1?: boolean; param2?: never; } interface IMyFunctionWithParam2 { param1?: never; param2?: boolean; } type TMyFunction = IMyFunctionWithParam1 | IMyFunctionWithParam2; const myFunction = ({ param1, param2 }: TMyFunction) => { if (param1) { return { hello: 'world' }; } if (param2) { return { goodbye: 'world' }; } return null; } const result1 = myFunction({ param1: true }); // 期望类型:{ hello: string; goodbye?: undefined; },实际为联合类型 const result2 = myFunction({ param2: true }); // 期望类型:{ goodbye: string; hello?: undefined; },实际为联合类型 const result3 = myFunction({}); // 期望类型:null,实际为联合类型
当前myFunction的返回值类型被推断为:
{ hello: string; goodbye?: undefined; } | { goodbye: string; hello?: undefined; } | null
我们需要让TypeScript精准识别result1的类型为{ hello: string; goodbye?: undefined; },result2和result3同理。
解决方案
方案1:使用函数重载
函数重载可以明确指定不同参数签名对应的返回类型,直接建立参数与返回值的关联:
interface IMyFunctionWithParam1 { param1?: boolean; param2?: never; } interface IMyFunctionWithParam2 { param1?: never; param2?: boolean; } type TMyFunction = IMyFunctionWithParam1 | IMyFunctionWithParam2; // 重载签名:定义三种参数场景对应的返回类型 function myFunction({ param1: true }: { param1: boolean }): { hello: string }; function myFunction({ param2: true }: { param2: boolean }): { goodbye: string }; function myFunction({}: {}): null; // 实现签名:保留原有逻辑 function myFunction({ param1, param2 }: TMyFunction) { if (param1) { return { hello: 'world' }; } if (param2) { return { goodbye: 'world' }; } return null; } // 此时类型推断完全符合预期 const result1 = myFunction({ param1: true }); // 类型:{ hello: string } const result2 = myFunction({ param2: true }); // 类型:{ goodbye: string } const result3 = myFunction({}); // 类型:null
方案2:泛型+条件类型关联参数与返回值
通过泛型捕获传入的参数类型,再用条件类型推导对应的返回值:
// 定义参数类型的联合 type MyFunctionParams = | { param1: boolean; param2?: never } | { param2: boolean; param1?: never } | {}; // 根据参数类型推导返回值类型 type MyFunctionReturn<T extends MyFunctionParams> = T extends { param1: true } ? { hello: string } : T extends { param2: true } ? { goodbye: string } : null; // 泛型函数实现 const myFunction = <T extends MyFunctionParams>(params: T): MyFunctionReturn<T> => { const { param1, param2 } = params; if (param1) { return { hello: 'world' } as MyFunctionReturn<T>; } if (param2) { return { goodbye: 'world' } as MyFunctionReturn<T>; } return null as MyFunctionReturn<T>; }; // 类型推断符合预期 const result1 = myFunction({ param1: true }); // 类型:{ hello: string } const result2 = myFunction({ param2: true }); // 类型:{ goodbye: string } const result3 = myFunction({}); // 类型:null
原代码问题原因
原代码中,函数参数是联合类型TMyFunction,TypeScript默认不会将联合类型的具体分支与返回值做关联推断,只会返回所有可能的返回类型的联合。通过重载或泛型条件类型,我们手动建立了参数分支与返回值的对应关系,让TypeScript能够精准推断。
内容的提问来源于stack exchange,提问作者Mike K
相关产品推荐
相关产品推荐

