TypeScript装饰器泛型类型变为unknown问题求助
解决方案
问题分析
两次尝试的核心问题:
- 第一次未正确推导原函数的返回值类型,导致
Result的value为unknown; - 第二次错误地将
Promise<string>直接放入Result,而非解析后的string类型。
正确实现代码
首先明确Result类型定义:
type Result<T, E> = { ok: true; value: T } | { ok: false; error: E };
实现带重试功能且返回Promise<Result<T, Error>>的装饰器:
import { retryDecorator, RetryConfig } from "ts-retry-promise"; function retryWithResult<TArgs extends any[], T>( config?: RetryConfig ): (fn: (...args: TArgs) => Promise<T>) => (...args: TArgs) => Promise<Result<T, Error>> { return (fn) => { // 先通过retryDecorator添加重试逻辑 const retriedFn = retryDecorator(config)(fn); // 包裹一层处理Result类型转换 return async (...args) => { try { const value = await retriedFn(...args); return { ok: true, value }; } catch (error) { return { ok: false, error: error instanceof Error ? error : new Error(String(error)) }; } }; }; }
关键说明
- 泛型捕获类型:通过
TArgs(原函数参数类型)和T(原函数Promise解析后的返回值类型),让TypeScript能正确推导最终Result的类型; - 分层包装:先借助
retryDecorator实现重试逻辑,再通过async/await解析Promise结果,最后用try/catch将成功值或错误包装为Result类型; - 错误处理:确保捕获的错误始终是
Error类型,避免非Error值导致的类型问题。
使用示例
// 原异步函数 async function fetchData(a: string): Promise<string> { if (Math.random() > 0.5) throw new Error("Fetch failed"); return `Data for ${a}`; } // 用装饰器包装后,类型为:(a: string) => Promise<Result<string, Error>> const retryFetchData = retryWithResult({ retries: 2 })(fetchData); // 使用时类型完全正确 async function test() { const result = await retryFetchData("test"); if (result.ok) { console.log(result.value); // 类型为string } else { console.error(result.error); // 类型为Error } }
内容的提问来源于stack exchange,提问作者Golan Kiviti
相关产品推荐
相关产品推荐

