在TypeScript中扩展React组件

The*_*ram 21 oop generics inheritance typescript reactjs

我正在使用React.js和TypeScript.有没有办法创建从其他组件继承但有一些额外的道具/状态的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
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,如果我把这个会失败this.setStateDerived,我得到一个错误的打字稿(类型的参数DerivedStates是不能分配给类型S).我想这不是特定于TypeScript的东西,而是将继承与泛型混合的一般限制(?).这有什么类型安全的解决方法吗?

UPDATE

我解决的解决方案(根据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 });
    }
}
Run Code Online (Sandbox Code Playgroud)

Dav*_*ret 11

您可以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
Run Code Online (Sandbox Code Playgroud)

顺便说一句,没有必要为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;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @Thegaram我必须更明确地让它工作:`返回{a:3}作为Base`作为S`.有点讨厌,但也许有一个原因.我更新了答案. (2认同)