ホーム>source

私はTypeScript/Reactプロジェクトに取り組んでおり、マルチステッププロセス用の汎用「ウィザード」コンポーネントを構築しています。ウィザードは、「パネル」コンポーネントプロパティの配列を受け取り、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>

次のエラーが表示されます。

Type '(typeof MyPanel)[]' is not assignable to type '(typeof WizardPanel)[]'.

Type 'typeof MyPanel' is not assignable to type 'typeof WizardPanel'.

Type 'MyPanel' is not assignable to type 'WizardPanel'.

Types of property 'props' are incompatible.

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

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

何が得られますか?この最後の行に来ているようです:

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

しかし、私が間違ったことを理解していない。 Readonly<{ children?: ReactNode; }> が見つからない  propComponentsのIWizardProps宣言で??

あなたの答え
  • 解決した方法 # 1

    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
    }
    
    

  • 前へ java - JPAクエリ:サブクエリをグループ化条件に結合する
  • 次へ javascript - アンカーにパディングを追加し、投稿テキストエディター内のボタンのスタイルを設定します