如何通过React-Redux的`connect`承载组件的通用定义

时间:2019-04-26 16:08:22

标签: reactjs typescript generics react-redux typescript-generics

我正在尝试编写一个通用的API查询包装器组件助手,并希望以通用类型(使用TypeScript)键入它,以便支持对特定API端点的参数和结果进行类型检查。除了React-Redux connect包装程序之外,我可以完成此工作,在该包装程序上似乎无法携带帮助程序的通用定义。

import React from "react";
import { connect } from "react-redux";
// import Api from "../somewhere";
declare const Api: { fetch: (params: any) => any };

interface Props<Result, Params> {
  accessToken?: string;
  params: Params;
  children: (fetchState: { loading: boolean; result?: Result; error?: any }) => React.ReactNode;
}

function ApiQueryComponent<Result, Params>({
  accessToken,
  params,
  children
}: Props<Result, Params>) {
  if (accessToken) {
    // Actually use the API here ...
    const promise = Api.fetch({ accessToken, params }) as Promise<Result>;
    const result = ({ id: 5, title: "shoes" } as unknown) as Result;
    return <div>{children({ loading: false, result })}</div>;
  } else {
    return <div>Please login first</div>;
  }
}

function mapStateToProps(state: { accessToken?: string }) {
  return {
    accessToken: state.accessToken
  };
}

export const ApiQuery = connect(mapStateToProps)(ApiQueryComponent);

// ======
// UI.tsx
// ======

declare const Product: React.ComponentType<{ product: any }>;
declare interface IProduct {}

// Does not type-check, "Expected 0 type arguments, but got 2"
export function UI() {
  return (
    <ApiQuery<IProduct, { id: number }> params={{ id: 5 }}>
      {({ loading, result: product, error }) => {
        if (loading) return <div>Loading...</div>;
        else if (error) return <div>Error :(</div>;
        else return <Product product={product} />;
      }}
    </ApiQuery>
  );
}

// Type-checks as expected, `product` is an `IProduct`
export function UI2() {
  return (
    <ApiQueryComponent<IProduct, { id: number }> params={{ id: 5 }}>
      {({ loading, result: product, error }) => {
        if (loading) return <div>Loading...</div>;
        else if (error) return <div>Error :(</div>;
        else return <Product product={product} />;
      }}
    </ApiQueryComponent>
  );
}

在此代码中,UI2可以正常工作,您可以告诉它参数和数据的类型。但是在UI中,由于使用connect包装器,因此无法指定此信息。

有人知道如何继承仿制药吗?我曾尝试以各种方式包装connect ed组件,但尚未使其起作用:(

0 个答案:

没有答案