【问题标题】:Adding type definitions to an HOC which injects props into a component将类型定义添加到将 props 注入组件的 HOC
【发布时间】:2017-12-07 18:07:41
【问题描述】:

我有一个“高阶组件”,它以以下方式实现(无类型)。

const Themeable = (mapThemeToProps) => {
  return (WrappedComponent) => {
    const themedComponent = (props, { theme: appTheme }) => {
      return <WrappedComponent
        {...props}
        theme={merge(
          {},
          defaultTheme,
          appTheme,
          mapThemeToProps(merge(defaultTheme, appTheme))
        )}
      >
    }
    themedComponent.contextTypes = { theme: PropTypes.object };
    return themedComponent;
  }
}

总结一下它的作用,它需要一个mapThemeToProps 函数。这将接收通过合并defaultTheme(由我的库提供)和appTheme(由ThemeProvider 组件通过上下文提供)创建的主题参数。然后它将创建一个扩展的Theme 并将其作为名为@9​​87654328@ 的道具传递给组件。在实践中,它会被如下使用(在这个范围内被称为Themeable):

const mapThemeToProps = (theme) => ({
  background: theme.palette.dark,
  color: theme.text.light,
});

function Greeting({ theme: { background, color } }) {
  return (
    <div style={{ background, color }}>
      Hello World!
    <div>
  )
}

export default Themeable(mapThemeToProps)(Greeting);

我很难为此功能开发正确的类型。 I found this pattern is very similar to something along the lines of connect from react-redux so have been working from their typings 作为我的起点。反正我有点迷茫,这基本上就是我所在的地方:

import { Theme } from 'types/Theme';

interface ThemeableComponentEnhancer {
  <P>(component: React.ComponentType<P>): React.ComponentClass<Pick<P, "theme"> & { theme: Theme }> & { WrappedComponent: React.Component<P>}
}

export interface Themeable {
  // calling it with no parameters returns a basic theme.
  (): Theme;
  // calling it with a function
  <TTheme = {}>(mapThemeToProps: MapThemeToPropsParam<TTheme>): ComponentEnhancer<{ theme: TTheme }>;
}

interface MapThemeToProps<TTheme> {
    (theme: TTheme): TTheme;
}

interface MapThemeToPropsFactory<TTheme> {
    (theme: Theme): MapThemeToProps<TTheme>;
}

type MapThemeToPropsParam<TTheme> = MapStateToPropsFactory<TTheme>

我很难理解这一点。这将如何在 TypeScript 中完成?

【问题讨论】:

    标签: javascript reactjs typescript


    【解决方案1】:

    Theme.ts

    export interface Theme {
      palette: {
        primary: string;
        secondary: string;
      };
    }
    
    export const theme: Theme = {
      palette: {
        primary: 'red',
        secondary: 'yellow'
      }
    };
    

    示例Rect 组件与Theme

    import * as React from 'react';
    import { Theme } from '../theme/Theme';
    import withTheme, { MapThemeToProps } from '../theme/withTheme';
    
    export interface RectThemeProps {
      titleColor?: string;
      bodyColor?: string;
    }
    
    export interface RectProps extends RectThemeProps {
      content?: string;
    }
    
    export class Rect extends React.Component<RectProps> {
      render() {
        const {titleColor, bodyColor, content} = this.props;
        return <div>{content && content}</div>;
      }
    }
    
    const mapThemeToProps: MapThemeToProps<
      RectThemeProps,
      Theme
      > = (theme) => {
      return {
        titleColor: theme.palette.primary,
        bodyColor: theme.palette.secondary
      };
    };
    
    export default withTheme(mapThemeToProps)(Rect);
    

    withTheme.ts

    import * as React from 'react';
    
    const ID = '__context_id__';
    
    export interface MapThemeToProps<M, T> {
      (theme: T): M;
    }
    
    export interface withTheme {
      <M, T>(mapThemeToProps: MapThemeToProps<M, T>):
        (c: React.ComponentType<M>) => React.ComponentType<M>;
    }
    
    export default <M, T>(
      mapThemeToProps: MapThemeToProps<M, T>
    ) => (Component: React.ComponentType<M>) => {
      return class extends React.Component<M> {
        render() {
          const theme = this.context[ID];
          return (
            <Component
              {...this.props}
              {...mapThemeToProps(theme.getTheme())}
            />
          );
        }
      };
    }
    

    【讨论】:

    • 真的可以在代码中使用一些解释或cmets,对于提出问题的人来说,这不是一个足够的答案。
    猜你喜欢
    • 2021-09-25
    • 2017-11-04
    • 2014-11-11
    • 1970-01-01
    • 2020-08-30
    • 2017-12-03
    • 1970-01-01
    • 2021-11-20
    • 2020-01-12
    相关资源
    最近更新 更多