typescript 有没有可能用泛型的签名来清空重载函数?

3bygqnnd  于 2023-03-13  发布在  TypeScript
关注(0)|答案(1)|浏览(175)

我正在编写一个简单的Axios Package 器函数,它结合了zod解析,并返回一个有区别的并集,以便更好地处理错误。在某些情况下,Axios的默认行为应该保留在它应该抛出任何错误的地方。我已经通过重载将{ throw: true }传递给config参数成功地实现了这个功能,我不喜欢的是实现的冗长。有没有办法让下面的重载更干燥?理想情况下,声明泛型SchemaParsed一次,而不是重复它们三次?

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?: Catch;
}

/**
 * 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 overload `config.catch` to throw unsuccessful api-call like native axios.
 */
async function axiosWrapper<
  Schema extends z.Schema = z.ZodUnknown,
  Parsed = z.output<Schema>,
>(url: Url, config: Config<Schema, false>): Promise<Result<Parsed>>;

async function axiosWrapper<
  Schema extends z.Schema = z.ZodUnknown,
  Parsed = z.output<Schema>,
>(url: Url, config: Config<Schema, true>): Promise<Parsed>;

async function axiosWrapper<
  Schema extends z.Schema = z.ZodUnknown,
  Parsed = z.output<Schema>,
>(url: Url, config: Config<Schema, boolean>): Promise<Result<Parsed> | Parsed> {
  // …implmentation
}
kninwzqo

kninwzqo1#

减少你必须编写的泛型的数量是可能的,并且通常可以删除重复的代码。然而,这也会改变你使用函数的方式。
例如,以下方法可行:

type AxiosWrapperFunction<
  Schema extends z.Schema = z.ZodUnknown,
  Parsed = z.output<Schema>
> = {
  (url: Url, config: Config<Schema, false>): Promise<Result<Parsed>>;
  (url: Url, config: Config<Schema, true>): Promise<Parsed>;
};

export const createAxiosWrapper = <
  Schema extends z.Schema = z.ZodUnknown,
  Parsed = z.output<Schema>
>(): AxiosWrapperFunction<Schema, Parsed> => {
  return (url: Url, config: Config<Schema, boolean>) => {
    /** implementation */
  };
}

在这种情况下,我们必须创建一个 Package 函数,因为它必须能够将泛型传递给实现函数。
缺点是,我们现在必须使用函数如下:

const axiosWrapper = createAxiosWrapper</** your generics */>();

axiosWrapper(/** your arguments */)

而不是能够做到:

axiosWrapper</** your generics */>(/** your arguments */)

我的建议是继续重写泛型并坚持使用函数重载的实现

相关问题