首页 > 解决方案 > 如何在 React 高阶组件中输入 defaultProps

问题描述

我的高阶组件无法识别在传递的组件中实现的 defaultProps。我怎样才能正确输入这个?

这是一个基本示例:

import React from 'react';

// HOC
const withTheme = <P extends {}>(Comp: React.ComponentType<P>) => {
    return Comp as React.ComponentType<P> & {
        defaultProps: typeof Comp['defaultProps'];
    };
}

class Button extends React.Component<{size: string }> {
    static defaultProps = {
        size: 'l'
    }
}

const ThemedButton = withTheme(Button)

// here's the problem:
// left-hand side is Partial or undefined
// right-hand side is defined, but `withTheme` can't infer it
ThemedButton.defaultProps = Button.defaultProps;

// Button works fine
const a = () => <Button />
// ThemedButton does not work fine
const b = () => <ThemedButton />

操场

有没有推荐的方法来使用这些道具并正确输入?

标签: reactjstypescript

解决方案


也许这符合您的要求。看起来有点复杂,因为defaultProps类型真的很难从Button. 最后我尝试了很多东西,结果如下:

const withTheme = <
  C extends React.ComponentType<any>, // Component type
  T, // Default theme props type
  Props = C extends React.ComponentType<infer R> ? R : never // Props type
>(
  Comp: C,
  defaultProps?: T extends Partial<Props> ? T : never
) => {
  return (
    props: Omit<Props, keyof (typeof Comp['defaultProps'] & T)> &
      Partial<typeof Comp['defaultProps'] & T> &
      JSX.LibraryManagedAttributes<C, { children?: ReactNode }>
  ) => <Comp {...defaultProps} {...props} />;
};

class Button extends React.Component<{
  size: string;
  id: number;
  theme: string;
}> {
  static defaultProps = {
    size: 'small',
  };
}

const a0 = () => <Button id={1} />; // Error
const b0 = () => <Button id={1} theme="dark" />; // OK

const ThemeButton1 = withTheme(Button);

const a1 = () => <ThemeButton1 id={1} />; // Error
const b1 = () => <ThemeButton1 id={1} theme="dark" />; // OK

const ThemeButton2 = withTheme(Button, {
  theme: 'dark',
});

const a2 = () => <ThemeButton2 />; // Error
const b2 = () => <ThemeButton2 id={1} />; // OK

操场


更新前

也许你可以试试,还有其他更好的选择让它不使用as

// change
typeof Comp['defaultProps']
// into
Partial<P>

推荐阅读