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

标签 reactjs typescript react-hooks

我有一个简单的 react 钩子(Hook),它接受一个参数,一个异步函数。它有效,但是在使用钩子(Hook)时我没有得到任何类型推断。具体来说,我试图让 typescript 推断正在传递的回调参数的类型。我提供了下面的代码以及我当前对该函数的使用情况。

Hook :

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”上时,我看到 const postOrder: (...args: any[]) => void 其中 args 在应该引用时被定义为 any[]传递到 Hook 的函数的参数类型(如果有)。

最佳答案

如果向 UseAsyncuseAsync 添加额外的泛型参数 A extendsknown[],则可以跟踪参数类型,并用它键入每个出现的 ...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];
};

当应用于测试函数时,postOrder 的类型具有实际的参数类型:

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

TypeScript playground

关于reactjs - Typescript:推断作为参数传递给另一个函数的回调函数的参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67221698/

相关文章:

javascript - 在设置状态 React JS 之前检查对象数组是否存在于对象数组中的简单方法

javascript - 刷新页面给出 Cannot GET/page_url in react-router 2

css - 保持覆盖文本的垂直居中对齐

javascript - 使用 Angular-CLI 正确配置脚本

angular - typescript ,固定。类型 'string' 不可分配给类型 'number'

reactjs - 如何使用键盘 Tab 键聚焦于 Material UI Link(不使用组件 ="button")

reactjs - 为什么异步函数中的多个 setState 调用会导致多次渲染?

javascript - react 自定义 Hook 中未定义 useHistory

javascript - React Native - 如何在其他组件之上创建和渲染组件

typescript - 有没有办法通过 tslint 规则在 Typescript 类上强制执行方法返回类型?