使用时的类型参数

Type argument at moment of use

我正在尝试构建一个通用工具来处理对我的应用程序中 React Query useQuery 请求的响应,并使用 TypeScript 构建它,以便正确输入数据。

在 parent 组件中,用例是这样的:

const queryResult = useQuery<MyResponseType, Error>('whatever');

return (
  <ReactQueryLoader useQueryResult={queryResult}>
    {data => {
      // Data should be of MyResponseType type, but is unknown
      return <pre>{JSON.stringify(data, null, 2)}</pre>;
    }}
  </ReactQueryLoader>
);

我试过这样定义这个 ReactQueryLoader:

import React from "react";
import { UseQueryResult } from "react-query";

import { Loading } from "./Loading";

interface ReactQueryLoaderProps {
  useQueryResult: UseQueryResult<unknown, Error>;
  handleError?: (error: Error) => void;
  children: (data: unknown) => JSX.Element;
}

export const ReactQueryLoader = ({
  useQueryResult,
  handleError = error => {
    console.error(error);
    throw new Error(error.message);
  },
  children,
}: ReactQueryLoaderProps): null | JSX.Element => {
  if (useQueryResult.isError) {
    handleError(useQueryResult.error);
    return null;
  }

  if (useQueryResult.isLoading) {
    return <Loading />;
  }

  return children(useQueryResult.data);
};

但是当我检查传递给 child 的 data 时,它不是预期响应数据的类型,而是未知的。作为对 TypeScript 有 mid-low-level 理解的人,我无法让它工作。我以为我可以应用与 中相同的模式,但我不知道在这种情况下该怎么做。

我试过这个:

interface ReactQueryLoaderProps {
  // ...
  children: <T extends unknown>(data: T) => JSX.Element;
}

但是在 parent 元素中得到了这个:

(parameter) data: T extends unknown

我也试过:

interface ReactQueryLoaderProps {
  useQueryResult:  UseQueryResult<T extends unknown, Error>;

但这引发了两个错误:

这可能吗?

这里的ReactQueryLoader函数需要是通用的,props类型也是如此。

可能看起来像这样:

interface ReactQueryLoaderProps<T extends UseQueryResult<unknown, Error>> {
  useQueryResult: T;
  handleError?: (error: Error) => void;
  children: (data: T['data']) => JSX.Element;
}

export function ReactQueryLoader<T extends UseQueryResult<unknown, Error>>({
  useQueryResult,
  handleError,
  children,
}: ReactQueryLoaderProps<T>): null | JSX.Element {
  //...
}

这里 ReactQueryLoader 现在是一个通用函数,它将查询结果类型捕获为 T 并将其传递给通用道具类型 ReactQueryLoaderProps.

ReactQueryLoaderProps 然后使用该类型作为 useQueryResult 的类型,并从该类型中提取 ['data'] 属性 作为 children 的类型函数参数。

See playground