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
}
}
ただし、Derived
でthis.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 });
}
}
タイプアサーションを使用すると、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;
}
}