Reactjs Typescript:推断作为参数传递给另一个函数的回调函数的参数

Reactjs Typescript:推断作为参数传递给另一个函数的回调函数的参数,reactjs,typescript,react-hooks,Reactjs,Typescript,React Hooks,我有一个简单的react钩子,它接受一个参数,一个异步函数。它可以工作,但是在使用钩子时,我没有得到任何类型推断。具体来说,我试图让typescript推断所传递回调的参数类型。我已经提供了下面的代码和我当前使用的函数 钩子: import { useCallback, useState } from "react"; type UseAsync<T> = [{ result: T; loading: boolean; error: string }, (...

我有一个简单的react钩子,它接受一个参数,一个异步函数。它可以工作,但是在使用钩子时,我没有得到任何类型推断。具体来说,我试图让typescript推断所传递回调的参数类型。我已经提供了下面的代码和我当前使用的函数

钩子:

import { useCallback, useState } from "react";

type UseAsync<T> = [{ result: T; loading: boolean; error: string }, (...args) => void];

export const useAsync = <T>(asyncFn: (...args) => Promise<T>): UseAsync<T> => {
  const [loading, setLoading] = useState(false);
  const [result, setResult] = useState(null);
  const [error, setError] = useState(null);

  const callback = useCallback(
    async (...args) => {
      try {
        setLoading(true);

        const result = await asyncFn(...args);

        setResult(result);
      } catch (e) {
        setError(e);
      } finally {
        setLoading(false);
      }
    },
    [asyncFn]
  );

  return [{ result, loading, error }, callback];
};

export default useAsync;
const [{ result, loading, error }, postOrder] = useAsync((data: INewOrderFormData) =>
    Axios.post("/api/order", data)
);

当我将鼠标悬停在VSCode中的“postOrder”上时,我看到
常量postOrder:(…args:any[])=>void
其中args被定义为any[],它应该引用传递到钩子中的函数的参数类型(如果有的话)。

如果添加一个额外的泛型参数
A extends unknown[]
同时输入
UseAsync
UseAsync
,并用它键入每个出现的
…args

结果是这样的(我不得不调整一些
null
类型,可能是因为代码没有使用
strictNullChecks
编译):


啊哈!成功了!非常感谢,现在有道理了:)
type UseAsync<T, A extends unknown[]> =
  [{ result: T | null; loading: boolean; error: string }, (...args: A) => void];

export const useAsync = <T, A extends unknown[]>(asyncFn: (...args: A) => Promise<T>): UseAsync<T,A> => {
  const [loading, setLoading] = useState(false);
  const [result, setResult] = useState<T | null>(null);
  const [error, setError] = useState<any>(null);

  const callback = useCallback(
    async (...args: A) => {
      try {
        setLoading(true);

        const result = await asyncFn(...args);

        setResult(result);
      } catch (e) {
        setError(e);
      } finally {
        setLoading(false);
      }
    },
    [asyncFn]
  );

  return [{ result, loading, error }, callback];
};
type INewOrderFormData = {}

const [{ result, loading, error }, postOrder] = 
  useAsync(async (data: INewOrderFormData, arg2: symbol) => 42);

type Test = typeof postOrder
// inferred type: (data: INewOrderFormData, arg2: symbol) => void