Typescript 通用格式化程序类型确定

问题描述 投票:0回答:1

我正在创建重载的 useFetch 挂钩,它具有可选的错误格式化程序。 错误格式化程序可以返回任何类型,因此该类型是通用的。 由于某种原因,打字稿不会从参数函数formatError分配泛型类型ErrType。 谁知道为什么,以及如何做?

type UseFetchReturnType<ResponseType, ErrType> = {
  data: ResponseType | null,
  error: ErrType | null,
  loading: boolean
};

function useFecth<ResponseType>(url: string): UseFetchReturnType<ResponseType, string>;
function useFecth<
  ResponseType,
  ErrType,
>(url: string, formatError: (x: any) => ErrType): UseFetchReturnType<ResponseType, ErrType>;

function useFecth<ResponseType>(url: string, formatError?: (x: any) => unknown) {
  ...
  ...
  ...
  return {
    data,
    error,
    loading,
  };
}


const { data: numArr, error: numberErr } = useFecth<number[]>('https://url1', (x: any): number => 7);
const { data: stringVal, error: boolErr } = useFecth<string>('https://url2', (x: any): boolean => false);
const { data: stringArr, error: stringErr } = useFecth<string[]>('https://url2');

我也尝试过简化的例子,它有效!我不明白为什么 useFetch 不这样做。

// Function return type used as a generic, which works
function fnWrapper(): string;
function fnWrapper<T>(callback: () => T): T;
function fnWrapper(cb?: () => unknown) {
  return  cb !== undefined ? cb() : 'default value';
}

const a = fnWrapper(() => 7);
const b = fnWrapper(() => 'String val');
const c = fnWrapper();

代码在这里:

typescript
1个回答
0
投票

TS 的一个限制是,在推断泛型时,如果提供了其中一个泛型,TS 将停止推断所有泛型。 这意味着当我们将响应通用参数传递给

useFetch
TS 时,不会尝试推断
ErrorType
的第二个通用参数。

因此,解决方法是在传递错误函数时需要第二个通用参数的重载。

type UseFetchReturnType<ResponseType, ErrType> = {
  data: ResponseType | null;
  error: ErrType;
  loading: boolean;
};

declare function useFetch<ResponseType>(
  url: string,
): UseFetchReturnType<ResponseType, null>;
declare function useFetch<ResponseType, ErrorResponse>(
  url: string,
  formatError: (args: any) => ErrorResponse,
): UseFetchReturnType<ResponseType, ErrorResponse>;
declare function useFetch<ResponseType, ErrorResponse>(
  url: string,
  formatError?: (args: any) => ErrorResponse,
): UseFetchReturnType<ResponseType, ErrorResponse>;

const { data: numArr, error: numberErr } = useFetch<
  number[],
  number
>("https://url1", (x: any) => 7);
const { data: stringVal, error: boolErr } = useFetch<string, boolean>(
  "https://url2",
  (x: any): boolean => false,
);
const { data: stringArr, error: stringErr } =
  useFetch<string[]>("https://url2");

© www.soinside.com 2019 - 2024. All rights reserved.