如何根据输入参数确定第三方函数的返回值类型?
问题与解决方案
问题背景
我正在对接一个第三方函数,它的返回类型标注为any(示例中实际定义为object),但真实返回结构完全由传入的outputParams参数决定。示例代码如下:
interface OutputParam { name: string; } // 第三方函数,无法修改 const executeStoredProc = (outputParams: OutputParam[]): object => { const retval = {}; for (let output of outputParams) { retval[output.name] = 'sample data'; } return retval; } const example = () => { const outputParams: OutputParam[] = [ { name: "Sandwich_ID" }, { name: "Sandwich_Has_Ketchup" }, ]; const exampleResult = executeStoredProc(outputParams); // 需求:让TypeScript识别exampleResult拥有Sandwich_ID和Sandwich_Has_Ketchup属性 const sandwichId = exampleResult.Sandwich_ID; // 当前会报错:类型“object”上不存在属性“Sandwich_ID” const sandwichHasKetchup = exampleResult.Sandwich_Has_Ketchup; // 同上 return { sandwichId, sandwichHasKetchup, }; };
我希望将exampleResult自动转换成与outputParams对应的类型,比如:
type ExampleOutput = { Sandwich_ID: unknown, Sandwich_Has_Ketchup: unknown, }
解决方案
有两种可行的方式实现需求,一种是手动类型断言,另一种是利用TypeScript泛型自动推导类型,后者更灵活。
方法一:手动类型断言
如果outputParams的结构固定,可以先手动定义目标类型,再通过类型断言将函数返回值转为该类型:
// 先定义预期类型 type ExampleOutput = { Sandwich_ID: unknown; Sandwich_Has_Ketchup: unknown; }; const example = () => { const outputParams: OutputParam[] = [ { name: "Sandwich_ID" }, { name: "Sandwich_Has_Ketchup" }, ]; // 断言返回值为目标类型 const exampleResult = executeStoredProc(outputParams) as ExampleOutput; // 此时TypeScript能识别属性,不会报错 const sandwichId = exampleResult.Sandwich_ID; const sandwichHasKetchup = exampleResult.Sandwich_Has_Ketchup; return { sandwichId, sandwichHasKetchup, }; };
这种方式简单直接,但缺点是如果outputParams的结构变化,需要同步修改ExampleOutput类型,维护成本较高。
方法二:泛型自动推导类型
通过封装一个泛型工具函数,让TypeScript自动根据outputParams的具体值推导返回类型,无需手动维护类型定义:
interface OutputParam { name: string; } // 第三方函数,无法修改 const executeStoredProc = (outputParams: OutputParam[]): object => { const retval = {}; for (let output of outputParams) { retval[output.name] = 'sample data'; } return retval; } // 封装泛型函数,自动推导返回类型 const executeStoredProcTyped = <T extends readonly OutputParam[]>( outputParams: T ): { [K in T[number]['name']]: unknown } => { // 类型断言兼容第三方函数的参数类型 return executeStoredProc(outputParams as OutputParam[]) as { [K in T[number]['name']]: unknown }; }; const example = () => { // 使用as const将数组转为只读元组,让TypeScript捕获每个name的具体字符串值 const outputParams = [ { name: "Sandwich_ID" }, { name: "Sandwich_Has_Ketchup" }, ] as const; // 调用封装后的函数,返回类型自动推导为对应的结构 const exampleResult = executeStoredProcTyped(outputParams); // TypeScript自动识别属性,支持代码提示,不会报错 const sandwichId = exampleResult.Sandwich_ID; const sandwichHasKetchup = exampleResult.Sandwich_Has_Ketchup; return { sandwichId, sandwichHasKetchup, }; };
原理说明:
- 使用
as const将outputParams转为只读元组,TypeScript会保留每个元素name的具体字符串字面量类型(而不是宽泛的string类型)。 - 泛型
T捕获这个只读元组的类型,通过T[number]['name']提取所有name的字面量集合。 - 利用映射类型
{ [K in T[number]['name']]: unknown }生成与outputParams对应的返回类型,属性名就是name的值,属性类型设为unknown(如果知道返回值的具体类型,可替换为对应类型,比如string)。
这种方式的优势是:只要修改outputParams的内容,返回类型会自动同步更新,无需手动修改类型定义,适合动态变化的场景。
内容的提问来源于stack exchange,提问作者estoner
相关产品推荐
相关产品推荐

