网站搜索

reactjs - 使用 TypeScript 严格类型化消费属性的 React 高阶组件


我正在尝试编写一些比仅仅注入属性更复杂的高阶 React 组件。这些 HOC 必须能够:

  • 接收未被(或仅可选择性地)转发给包装组件的属性
  • 为封装的组件提供一些新属性
  • 在创建它们时接受额外的参数

据我所知,这意味着我们必须有三种类型:

  1. HOC 提供给被包装组件的属性
  2. HOC 使用的属性,但被包裹的组件不一定关心这些属性
  3. HOC 不关心的被包装组件的属性

我有以下代码可以正常工作,但我找不到在将 props 传递给封装组件时避免 any 类型转换的方法:

import React, { ComponentType } from 'react';

// Props of the wrapped component without the props provided by the HOC
type StrictWrappedProps<WrappedProps, InjectedProps> = Omit<
  WrappedProps,
  keyof InjectedProps
>;

type WrappedComponent<WrappedProps, InjectedProps> = ComponentType<
  WrappedProps & InjectedProps
>;

type HOCType<WrappedProps, InjectedProps, OwnProps> = ComponentType<
  OwnProps & StrictWrappedProps<WrappedProps, InjectedProps>
>;

type LengthifyOwnProps = {
  name: string;
};

type LengthifyInjectedProps = {
  length: number;
};

export const lengthify = <WrappedProps extends {}>(
  Wrapped: WrappedComponent<WrappedProps, LengthifyInjectedProps>,
  multiplier: number
): HOCType<WrappedProps, LengthifyInjectedProps, LengthifyOwnProps> => ({
  name,
  ...props
}) => {
  const length = name.length * multiplier;
  return <Wrapped {...props as any} length={length} />;
};

这里是该高阶组件的一个使用示例:

const myComp = ({ bool, length }: { bool: boolean; length: number }) => (
  <p>
    Bool is: {bool}. Length is: {length}
  </p>
);

const EnhancedMyComp = lengthify(myComp, 2);

const usage = () => <EnhancedMyComp bool={true} name="Hello" />;

any 类型转换是一个小的变通办法,但我想找到更严格的类型定义方法。

React TypeScript 关于 HOCs 的速查表链接到了 TypeScript 仓库中的这个 bug,但它似乎或多或少已经解决,并且只与注入属性的 HOC 有关。StackOverflow 上的其他问题也似乎是关于注入属性,或者对 ComponentType 类型的困惑。