能否简化含泛型的重载函数签名,使其符合DRY原则?
优化Axios Zod包装函数的重载冗余问题
首先修正原代码里的笔误:Config接口中的throw?: Catch应该改为throw?: Throw,否则类型会不匹配。
针对你想要减少泛型重复声明的需求,可以通过条件类型+单一泛型签名来优化,只需要声明一次泛型参数,就能覆盖两种返回逻辑:
import type { AxiosRequestConfig } from 'axios'; import * as z from 'zod'; import * as URLS from '~/constants/api-url-constants'; import { coerceError } from '~/utils'; type Result<T> = { ok: true; response: T } | { ok: false; error: Error }; type Url = string | ((urls: typeof URLS) => string); interface Config<Schema extends z.Schema, Throw extends boolean> extends AxiosRequestConfig { schema?: Schema | ((zod: typeof z) => Schema); throw?: Throw; // 修正原笔误:Catch → Throw } /** * Axios wrapper which accepts Zod-schema to parse * response data and return typed response inferred from schema's output type. * Schema validations happens in `config.transformResponse`, * meaning that failed Zod parsing is able to be intercepted. * * Returns discriminated union by default for error handling. * Use `config.throw: true` to throw unsuccessful api-call like native axios. */ async function axiosWrapper< Schema extends z.Schema = z.ZodUnknown, Parsed = z.output<Schema>, Throw extends boolean = false // 新增默认值为false,对应默认返回Result的行为 >( url: Url, config: Config<Schema, Throw> ): Promise<Throw extends true ? Parsed : Result<Parsed>> { // …实现逻辑保持不变,内部可通过config.throw的值分支处理: // 比如 if (config.throw) { 抛出错误 } else { 返回Result联合类型 } }
优化关键点:
- 只在函数顶层声明一次泛型参数
Schema、Parsed和Throw,避免重复冗余。 - 利用TypeScript的条件类型
Throw extends true ? Parsed : Result<Parsed>自动推导返回值类型:- 当传入
{ throw: true }时,返回Promise<Parsed>(和原生Axios行为一致); - 默认或传入
{ throw: false }时,返回Promise<Result<Parsed>>(判别式联合类型)。
- 当传入
- 给
Throw设置默认值false,保留原函数默认返回错误联合类型的行为。
这样既保留了原有的类型安全和两种错误处理模式,又大幅简化了函数签名的冗余度。
内容的提问来源于stack exchange,提问作者Audun Olsen
相关产品推荐
相关产品推荐

