首页 > 解决方案 > 函数参数返回类型的打字稿类型推断

问题描述

在我的反应项目中,我用这种模式声明了我的 api 请求:

export type LoginApiResponse = {
  token: string,
  user: User
}

export function login(email: string, password: string): Promise<LoginApiResponse> {
  return AuthService.signinWithEmailAndPassword(email, password)
}

我通过自定义钩子使用它们

export function useApi<T, Fn extends (...args: any[]) => Promise<T>>(
  fn: Fn
) {
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState();
  const execute = async (...params: Parameters<Fn>) => {

    setLoading(true);

    try {
      const result = await fn(...params);
      setLoading(false);
      return result;
    } catch (err) {
      console.warn("sideEfect execution error", err, JSON.stringify(err));
      setError(err);
      setLoading(false);
      throw (error);
    }
  };
  return { loading, execute, error };
}

像这样的实现

const loginExecutor = useApi<LoginApiResponse, typeof api.login>(api.login)

通过这种方式,我封装了给定 api 请求的加载和错误状态,而且我有完整的输入支持

在此处输入图像描述

在此处输入图像描述

问题

现在我的问题是:有没有办法利用 typescript 类型推断来推断 fn 函数的返回类型和参数类型,以便能够编写

useApi(api.login)

代替

useApi<LoginApiResponse, typeof api.login>(api.login)

同时保持相同的强类型?

标签: typescripttypescript-typingstypescript-generics

解决方案


我看到您的示例推断出除了响应之外的所有内容。它有以下类型:

const loginExecutor = useApi(login)

const loginExecutor: {
    loading: boolean;
    execute: (email: string, password: string) => Promise<unknown>;
    error: string;
}

试一试TS Playground


我更新useApi以单独提取参数和返回类型:

export function useApi<A extends any[], T>(
  fn: (...args: A) => Promise<T>
)

所以现在我们得到以下类型:

const loginExecutor = useApi(login)
const loginExecutor: {
    loading: boolean;
    execute: (email: string, password: string) => Promise<LoginApiResponse>;
    error: string;
}

试一试TS Playground


请注意,我的示例在 TS >= 4 上进行了测试。


推荐阅读