在TypeScript中扩展React组件 [英] Extending React components in TypeScript

查看:129
本文介绍了在TypeScript中扩展React组件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆