TypeScript工厂函数返回函数包装器的泛型嵌套类型定义问题
解决TypeScript工厂函数泛型类型推导问题
问题根源
原代码中createSafeFactory的泛型U和F被定义为无约束的宽泛函数类型,无法关联后续被包装函数的返回值类型T和错误类型E,导致TypeScript无法推断出onOk(result)和onErr(error)的具体类型,最终退化为unknown。
修改后的实现代码
const mayThrow = (fail: boolean) => { if (fail) { throw new Error('failed') } return 'ok' } type Ok<T> = { ok: true, value: T } type Err<E> = { ok: false, error: E } type Result<T, E> = Ok<T> | Err<E> const onOk = <T>(value: T): Ok<T> => ({ ok: true, value }) const onErr = <E>(error: E): Err<E> => ({ ok: false, error }) function createSafeFactory< U extends <T>(value: T) => unknown, F extends <E>(error: E) => unknown >(onOk: U, onErr: F) { // 提取U在输入类型T时的返回类型 type OkResult<T> = U extends <X>(x: X) => infer R ? R : never; // 提取F在输入类型E时的返回类型 type ErrResult<E> = F extends <X>(x: X) => infer R ? R : never; return <A extends any[], T, E = unknown>( fn: (...args: A) => T, errorFn?: (error: unknown) => E ) => { return (...args: A): OkResult<T> | ErrResult<E> => { try { const result = fn(...args); // 类型断言帮助TypeScript关联泛型参数T return onOk(result) as OkResult<T>; } catch (e) { const error = errorFn ? errorFn(e) : (e as E); // 类型断言帮助TypeScript关联泛型参数E return onErr(error) as ErrResult<E>; } }; }; } // 测试 const safe = createSafeFactory(onOk, onErr) // const safe: <A extends any[], T, E = unknown>(fn: (...args: A) => T, errorFn?: ((error: unknown) => E) | undefined) => (...args: A) => Ok<T> | Err<E> const safeFn = safe(mayThrow) // const safeFn: (fail: boolean) => Ok<string> | Err<unknown> const res = safeFn(true) // const res: Ok<string> | Err<unknown> if (res.ok) { const data = res.value // const data: string // 现在类型正确推导为string } // 带errorFn的测试 const safeFnWithCustomError = safe(mayThrow, e => (e as Error).message) // const safeFnWithCustomError: (fail: boolean) => Ok<string> | Err<string>
关键改动说明
- 泛型约束收紧:将
U和F约束为泛型函数类型,确保它们能接收任意类型的输入,并返回与输入类型绑定的结果,为后续类型关联打下基础。 - 动态返回类型定义:通过
OkResult<T>和ErrResult<E>两个条件类型,提取U和F在接收T/E类型输入时的具体返回类型。 - 类型断言辅助推断:由于TypeScript无法自动推断泛型函数的实例化类型,通过
as OkResult<T>和as ErrResult<E>帮助编译器关联正确的类型参数。 - 错误类型默认值:给
E设置默认值unknown,处理未传入errorFn时的错误类型推断。
内容的提问来源于stack exchange,提问作者eakl
相关产品推荐
相关产品推荐

