代码之家  ›  专栏  ›  技术社区  ›  tcmoore

将泛型类型的实现传递给反应组件属性

  •  0
  • tcmoore  · 技术社区  · 8 年前

    我正在进行一个TypeScript/React项目,我们正在为多步骤流程构建一个通用的“向导”组件。向导是一个包装器,它接受一个“panel”组件属性数组,并通过IWizardPanelProps接口向每个组件公开导航逻辑。

    export interface IWizardPanelProps {
      changePanel: (increment: number) => void;
    }
    
    export class WizardPanel<T> extends React.Component<IWizardPanelProps & T>{
      constructor(props: IWizardPanelProps & T) {
        super(props);
      }
    }
    
    interface IWizardProps {
      panelComponents: (typeof WizardPanel)[],
      showControls?: boolean // Hidden by default - assumes panels themselves handle pagination
    }
    
    interface IWizardState {
      panelIndex: number
    }
    
    export class Wizard extends React.Component<IWizardProps, IWizardState> {
      constructor(props: IWizardProps) {
        super(props);
    
        this.state = {
          panelIndex: 0
        }
      }
    
      changePanel = (increment: number) => {
        const newIndex = this.state.panelIndex + increment;
    
        this.setState({ panelIndex: newIndex });
      };
    
      render() {
        const { panelComponents, showControls } = this.props;
    
        return (
          <div>
            <p><strong>Ye olde Wizard Component! (This is a placeholder, but the functionality is mostly there)</strong></p>
            {panelComponents.map((Panel, key) => (
              <div className={key === this.state.panelIndex ? undefined : 'hidden'} key={key}>{<Panel {...this.props} changePanel={this.changePanel}></Panel>}</div>
            ))}
            {showControls && <div>
                <button disabled={this.state.panelIndex === 0} onClick={() => this.changePanel(-1)}>
                Previous
              </button>
              <button disabled={this.state.panelIndex === panelComponents.length - 1} onClick={() => this.changePanel(1)}>
                Next
              </button>
            </div>}
          </div>
        );  
      }
    }
    

    然后,当我们创建面板组件时,我们这样做:

    interface IMyPanelProps {
      ...
    }
    
    
    export class MyPanel extends WizardPanel<IMyPanelProps> {
      constructor(props: IWizardPanelProps & IMyPanelProps) {
        super(props);
      }
      render() {
        ...
      }
      ...
    }
    

    很好,对吧?

    <Wizard panelComponents={[ MyPanel ]}></Wizard>
    

    我们得到以下错误:

    向导面板)[]。

    类型“typeof MyPanel”不能分配给类型“typeof” 向导面板'。

    类型“MyPanel”不能分配给类型“WizardPanel”。

    键入'Readonly<{children?:ReactNode;}><Readonly<IWizardPanelProps&IMyPanelProps>'不能分配给'Readonly<{children'类型?:ReactNode;}><只读<IWizardPanelProps&T>'。

    键入'Readonly<{children?:ReactNode;}><只读<IWizardPanelProps&IMyPanelProps>'不能分配给类型“只读<IWizardPanelProps&T>”。

    给什么?好像是最后一句话:

    Readonly<{ children?: ReactNode; }> & Readonly< IWizardPanelProps & IMyPanelProps>' is not assignable to type 'Readonly< IWizardPanelProps & T>

    但我不明白我做错了什么。我们怎么会错过 Readonly<{ children?: ReactNode; }>

    1 回复  |  直到 8 年前
        1
  •  1
  •   Titian Cernicova-Dragomir    8 年前

    你可以使用 React.ComponentType 键入。这是定义组件类型的预期方式。

    interface IWizardProps {
        panelComponents: React.ComponentType<IWizardPanelProps>)[],
        showControls?: boolean 
    }
    

    问题是 WizardPanel

    export class BasicWizardPanel extends WizardPanel<{}>{}
    
    interface IWizardProps {
        panelComponents: (typeof BasicWizardPanel)[],
        showControls?: boolean // Hidden by default - assumes panels themselves handle pagination
    }
    
    推荐文章