【问题标题】:Can't properly type the following HOC function无法正确键入以下 HOC 函数
【发布时间】:2021-03-15 21:52:11
【问题描述】:

我编写了一个我无法正确输入的 HOC 函数(这是预期的,因为我是 TypeScript 初学者,甚至是类型初学者)。这是函数:

const withLayout = (LayoutComponent, layoutProps = {}) => (WrappedComponent) => {
  return function WithLayout(props) {
    return (
      <LayoutComponent {...layoutProps}>
        <WrappedComponent {...props} />
      </LayoutComponent>
    )
  }
}

我是这样使用的:

interface LayoutProps { a: string, b: string }

interface IndexProps { c: string, d: string }

class Layout extends React.Component<LayoutProps> { }

class Index extends React.Component<IndexProps> { }

withLayout(Layout, { a: 'a', b: 'b' })(Index)

这是我尝试输入的内容:

const withLayout = <LP extends JSX.IntrinsicAttributes & { children?: React.ReactNode }>(
  LayoutComponent: React.ComponentType<LP>,
  layoutProps: LP = {}
) => <WP extends JSX.IntrinsicAttributes & { children?: React.ReactNode }>(
  WrappedComponent: React.ComponentType<WP>
) => {
    return function WithLayout(props: WP): JSX.Element {
      return (
        <LayoutComponent {...layoutProps}>
          <WrappedComponent {...props} />
        </LayoutComponent>
      )
    }
  }

我有几个问题,正如您在TypeScript playground 中看到的那样。我意识到我应该允许 layoutPropsprops 分别成为 LayoutComponentWrappedComponent 道具的对象,但我真的无法弄清楚将它传达给 TypeScript 的正确方法。有什么建议吗?

【问题讨论】:

  • 您不能将默认的空对象作为layoutProps 传递,因为它没有所需的道具。你的泛型基本上没有被推断出来,所以我不得不玩弄这个,看看发生了什么。

标签: reactjs typescript react-typescript


【解决方案1】:

问题 #1:默认道具

参数layoutProps 必须是LP 类型,其中LP 是布局组件的道具。您不能使用空对象作为 layoutProps 的默认值,因为它没有所需的道具。我们根本不能有默认值,因为我们不知道LP 是什么,所以我们不可能满足未知类型的要求。

问题 #2:extends 类型

您声明LayoutComponentWrappedComponent 的props 必须扩展JSX.IntrinsicAttributes &amp; { children?: React.ReactNode }。这种类型没有必需的属性,所以技术上你的组件应该可以分配给它,但是没有重叠会导致 Typescript 类型推断阻塞。

我们应该得到一个更有用的错误,例如“这些类型没有共同的属性”。相反,它只是不推断类型。它使用您的 extends 子句作为类型,然后给您一个错误,指出这些道具 JSX.IntrinsicAttributes &amp; { children?: React.ReactNode } 不能用作组件的道具,因为它们缺少组件所需的属性。

我们可以通过扩大extends 条件(甚至完全删除它)来解决这个问题。使用LP extends {},可以正确推断组件的实际道具。

const withLayout = <LP extends {}>(
  LayoutComponent: React.ComponentType<LP>,
  layoutProps: LP
) => <WP extends {}>(
  WrappedComponent: React.ComponentType<WP>
) => {
    return function WithLayout(props: WP): JSX.Element {
      return (
        <LayoutComponent {...layoutProps}>
          <WrappedComponent {...props} />
        </LayoutComponent>
      )
    }
  }

Typescript Playground Link

【讨论】:

  • 谢谢!我仍然有一些担忧,但我想我会提出另一个问题,因为它有点不同。
猜你喜欢
  • 2021-10-05
  • 2019-03-25
  • 2019-02-22
  • 2015-04-20
  • 2023-02-14
  • 1970-01-01
  • 2020-03-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多