我正在创建重载的 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();
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");