Typescript:具有多个泛型函数作为参数的函数

Typescript: Function with multiple generic functions as params

提问人:paternostrox 提问时间:11/8/2023 最后编辑:paternostrox 更新时间:11/8/2023 访问量:42

问:

我正在尝试扩展这个现有函数(自定义反应钩子),它目前需要两个通用的获取函数,并将它们的响应数据作为命名元组以及一些辅助变量返回。我需要它接受任意数量的函数作为参数,然后返回一个名为元组的拟合,其中包含相应的响应数据类型(和辅助数据)。

我尝试使用不同类型的 rest 参数,但仍然没有运气,似乎无法使函数返回正确的结构。任何帮助都是值得赞赏的!

export function useFetchMultipleDataMunicipio<T0, T1>(
    f0: (routeProps: IMunicipioRouteProps, prestacaoContext: IPrestacaoContextProps, settings: ISettings) => AxiosPromise<T0>,
    f1: (routeProps: IMunicipioRouteProps, prestacaoContext: IPrestacaoContextProps, settings: ISettings) => AxiosPromise<T1>,
) {

    const routeProps = useMunicipioContext().municipioRouteProps;
    const prestacaoContext = usePrestacaoContext();
    const { settings } = useSettingsContext();

    const [dataTuple, setDataTuple] = useState<[T0, T1]>();
    const [loading, setLoading] = useState(true);

    useEffect(() => {
        if (_.isEmpty(routeProps) || prestacaoContext.loading) {
            return;
        }

        Promise.all([f0(routeProps, prestacaoContext, settings), f1(routeProps, prestacaoContext, settings)])
            .then((response) => {
                const newDataTuple: [T0,T1] = [response[0].data, response[1].data];
                setDataTuple(newDataTuple);
            })
            .finally(() => {
                setLoading(false);
            });

        return () => {
            setDataTuple(undefined);
            setLoading(true);
        }

    }, [routeProps, prestacaoContext.loading]);

    return { dataTuple, loading, routeProps, prestacaoContext, settings };
}
ReactJS TypeScript 泛型 元组

评论


答:

1赞 Ben 11/8/2023 #1

我想你正在寻找这样的东西:

type FetchFunction<T> = (
  routeProps: IMunicipioRouteProps,
  prestacaoContext: IPrestacaoContextProps,
  settings: ISettings
) => AxiosPromise<T>;

type FetchFunctionResponseTypes<T extends Array<FetchFunction<unknown>>> = {
  [P in keyof T]: T[P] extends FetchFunction<infer R> ? R : never;
};

然后,您应该能够将这些类型与钩子声明一起使用,如下所示:

function useFetchMultipleDataMunicipio<T extends Array<FetchFunction<unknown>>>(...args: T) {
     // ...
     const [dataTuple, setDataTuple] =
      useState<FetchFunctionResponseTypes<typeof args>>();

     // ...
     useEffect(() => {
         const promises = args.map(func => func(routeProps, prestacaoContext, settings));
         Promise.all(promises)
           .then((response) => {
             const newDataTuple = response.map(
               (res) => res.data
             ) as FetchFunctionResponseTypes<T>;
             setDataTuple(newDataTuple);
           })
           .finally(() => {
            setLoading(false);
          });
     }, [routeProps, prestacaoContext.loading]);

     return { dataTuple, loading, routeProps, prestacaoContext, settings };
}

评论

1赞 paternostrox 11/10/2023
完美无缺,谢谢Ben