【问题标题】:ApolloClient Typescript Higher Order Component issue (not assignable to type)ApolloClient Typescript 高阶组件问题(不可分配给类型)
【发布时间】:2020-05-01 15:17:42
【问题描述】:

我正在尝试在 React Native 应用程序中创建一个 HOC,但在使定义正常工作时遇到了问题。

interface IWithApolloClientComponentProps {
    apolloClient: ApolloClient<any>;
}
export function withApolloClient<
    P extends IWithApolloClientComponentProps, 
    R = Omit<P, keyof IWithApolloClientComponentProps>
>(
    Component: React.ComponentType<P>
): React.ComponentType<R> {
        return function BoundComponent(props: R) {
            return <ApolloConsumer>{client => <Component {...props} apolloClient={client} />} . 
        </ApolloConsumer>;
    };
}

我的 VSCode 一直报以下错误:

Type 'R & { apolloClient: ApolloClient<object>; }' is not assignable to type 'IntrinsicAttributes & P & { children?: ReactNode; }'.
  Type 'R & { apolloClient: ApolloClient<object>; }' is not assignable to type 'P'.
'R & { apolloClient: ApolloClient<object>; }' is assignable to the constraint of type 'P', but 'P' could be instantiated with a different subtype of constraint 'IWithApolloClientComponentProps'.ts(2322)

有人看到我在这里做错了什么吗?

【问题讨论】:

标签: typescript react-native apollo-client


【解决方案1】:

几乎在那里。通用的R = Omit&lt;P, keyof IWithApolloClientComponentProps&gt; 意味着R 可以设置为任何值,但默认为Omit&lt;P, keyof IWithApolloClientComponentProps&gt;。我们不希望这是一个通用的 - 它应该始终具有相同的 Omit 值。

如果我们试试这个:

export function withApolloClient<P extends IWithApolloClientComponentProps>(
  Component: React.ComponentType<P>
): React.ComponentType<Omit<P, keyof IWithApolloClientComponentProps>> {
  return function BoundComponent(
    props: Omit<P, keyof IWithApolloClientComponentProps>
  ) {
    return (
      <ApolloConsumer>
        {(client) => <Component {...props} apolloClient={client} />}
      </ApolloConsumer>
    );
  };
}

更好,但我们仍然得到一个错误:

'Pick

> & { apolloClient: ApolloClient; }' 可分配给“P”类型的约束,但“P”可以用约束“IWithApolloClientComponentProps”的不同子类型来实例化

比较这两种类型,我们从P 中删除了键"apolloClient",然后将ApolloClient&lt;object&gt; 属性添加到同一个键中。所以基本上它不能分配的唯一方法是如果P 需要特定类型的ApolloClient 而不是&lt;object&gt;

知道了这一点,您可能会很乐意断言 {...props as P}

还有另一种不需要as 断言的方法。不是P 指代包括IWithApolloClientComponentProps 在内的所有道具,而是使用P 来描述其他道具。

export function withApolloClient<P extends object>(
  Component: React.ComponentType<P & IWithApolloClientComponentProps>
): React.ComponentType<P> {
  return function BoundComponent(props: P) {
    return (
      <ApolloConsumer>
        {(client) => <Component {...props} apolloClient={client} />}
      </ApolloConsumer>
    );
  };
}

这里没有错误,因为我们的内部组件采用客户端类型ApolloClient&lt;any&gt;

【讨论】:

    猜你喜欢
    • 2019-07-01
    • 2020-07-12
    • 2019-07-25
    • 2021-04-17
    • 1970-01-01
    • 1970-01-01
    • 2022-08-23
    • 2018-09-19
    • 1970-01-01
    相关资源
    最近更新 更多