在TypeScript中扩展React组件 [英] Extending React components in TypeScript
问题描述
我在使用TypeScript的React.js。有什么办法可以创建从其他组件继承,但有一些额外的道具/状态的React组件?
我想要实现的是这样的: p>
接口BaseStates {
a:number;
}
类GenericBase< S扩展BaseStates>扩展React.Component< void,S> {
protected getBaseInitialState():BaseStates {
return {a:3};
}
}
class Base扩展GenericBase< BaseStates> {
getInitialState():BaseStates {
return super.getBaseInitialState();
}
}
接口DerivedStates扩展了BaseStates {
b:number;
}
类Derived extends GenericBase< DerivedStates> {
getInitialState():DerivedStates {
var initialStates = super.getBaseInitialState()as DerivedStates; //不安全?
initialStates.b = 4;
return initialStates
}
}
然而,这会失败如果我在 Derived
中调用 this.setState
,我得到一个TypeScript错误(参数类型为 DerivedStates
不可分配给类型 S
)。我想这不是一个特定于TypeScript的东西,而是继承与泛型(?)混合的一个普遍限制。是否有任何类型安全的解决方法?
更新
解决方案我决定了(基于David Sherret的回答):
$ b $ pre $ 接口BaseStates {
a:number;
}
类GenericBase< S扩展BaseStates>扩展React.Component< void,S> {
constructor(){
super();
this.state = this.getInitialState();
}
getInitialState():S {
return {a:3} as S;
}
update(){
this.setState({a:7} as S);
}
}
接口DerivedStates扩展了BaseStates {
b:number;
}
类Derived extends GenericBase< DerivedStates> {
getInitialState():DerivedStates {
var initialStates = super.getInitialState();
initialStates.b = 4;
返回initialStates;
update(){
this.setState({a:7,b:4});
$ div $解析方案
你可以通过使用类型断言在 Derived
中一次性设置状态的一些属性:
this.setState({b:4}作为DerivedStates); //做这个
this.setState({a:7}作为DerivedStates); //或这个
this.setState({a:7,b:4}); //或这个
顺便说一下,不需要为 getInitialState
...你可以这样做:
class GenericBase< S extends BaseStates>扩展React.Component< void,S> {
constructor(){
super();
this.state = this.getInitialState();
}
保护getInitialState(){
返回{a:3}为BaseStates为S;
}
}
类Derived extends GenericBase< DerivedStates> {
getInitialState(){
var initialStates = super.getInitialState();
initialStates.b = 4;
返回initialStates;
}
}
I'm using React.js with TypeScript. Is there any way to create React components that inherit from other components but have some additional props/states?
What I'm trying to achieve is something like this:
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
}
}
However, this will fail if I call this.setState
in Derived
, I get a TypeScript error (parameter of type DerivedStates
is not assignable to type S
). I suppose this is not a TypeScript-specific thing, but a general limitation of mixing inheritance with generics (?). Is there any type-safe workaround for this?
UPDATE
The solution I settled on (based on the answer of 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 });
}
}
You can set only a few properties of the state at once in Derived
by using a type assertion:
this.setState({ b: 4 } as DerivedStates); // do this
this.setState({ a: 7 } as DerivedStates); // or this
this.setState({ a: 7, b: 4 }); // or this
By the way, no need to have different names for getInitialState
... you could just do:
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;
}
}
这篇关于在TypeScript中扩展React组件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!