web-dev-qa-db-ja.com

TypeScriptでのReactコンポーネントの拡張

TypeScriptでReact.jsを使用しています。 React他のコンポーネントから継承するが、追加の小道具/状態があるコンポーネントを作成する方法はありますか?

私が達成しようとしているのは次のようなものです:

interface BaseStates {
    a: number;
}

class GenericBase<S extends BaseStates> extends React.Component<void, S> {
    protected getBaseInitialState(): BaseStates {
        return { a: 3 };
    }
}

class Base extends GenericBase<BaseStates> {
    getInitialState(): BaseStates {
        return super.getBaseInitialState();
    }
}

interface DerivedStates extends BaseStates {
    b: number;
}

class Derived extends GenericBase<DerivedStates> {
    getInitialState(): DerivedStates {
        var initialStates = super.getBaseInitialState() as DerivedStates; // unsafe??
        initialStates.b = 4;
        return initialStates
    }
}

ただし、Derivedthis.setStateを呼び出すと失敗します。TypeScriptエラーが発生します(タイプDerivedStatesのパラメーターはタイプSに割り当てることができません)。これはTypeScript固有のものではなく、ジェネリックと継承を混在させる一般的な制限(?)だと思います。これにはタイプセーフな回避策はありますか?

[〜#〜]更新[〜#〜]

私が解決した解決策(David Sherretの回答に基づく):

interface BaseStates {
    a: number;
}

class GenericBase<S extends BaseStates> extends React.Component<void, S> {
    constructor() {
        super();
        this.state = this.getInitialState();
    }

    getInitialState(): S {
        return { a: 3 } as S;
    }

    update() {
        this.setState({ a: 7 } as S);
    }
}

interface DerivedStates extends BaseStates {
    b: number;
}

class Derived extends GenericBase<DerivedStates> {
    getInitialState(): DerivedStates {
        var initialStates = super.getInitialState();
        initialStates.b = 4;
        return initialStates;
    }

    update() {
        this.setState({ a: 7, b: 4 });
    }
}
21
Thegaram

タイプアサーションを使用すると、Derivedで一度に設定できる状態のプロパティは数個のみです。

this.setState({ b: 4 } as DerivedStates); // do this
this.setState({ a: 7 } as DerivedStates); // or this
this.setState({ a: 7, b: 4 });            // or this

ちなみに、getInitialStateに別の名前を付ける必要はありません...

class GenericBase<S extends BaseStates> extends React.Component<void, S> {
    constructor() {
        super();        
        this.state = this.getInitialState();
    }

    protected getInitialState() {
        return { a: 3 } as BaseStates as S;
    }
}

class Derived extends GenericBase<DerivedStates> {
    getInitialState() {
        var initialStates = super.getInitialState();
        initialStates.b = 4;
        return initialStates;
    }
}
11
David Sherret