使用通用状态的React Component中的构造函数中的初始化状态

时间:2019-06-13 14:35:44

标签: reactjs typescript

这是React + Typescript问题。 我有一个使用道具和状态的两个泛型的组件。

interface Props {
    foo: string;
}
interface State {
    bar: string;
}
class Foo<
    P extends Props = Props,
    S extends State = State
> extends React.Component<P, S> {
    constructor(props: P) {
        super(props);

        this.state = { bar: "asd" };
    }
}

发现在构造函数中对this.state的配属是错误消息:

  

输入'{bar:“ asd”; }”不可分配为“ Readonly(S)”类型

当您从类声明中删除泛型并将State接口直接传递给React.Component<P, State>时,一切正常。

我的问题是如何避免这种错误?我需要以一种可以验证已知状态参数(例如本例中的bar)但允许指定其他属性的方式来初始化状态。

3 个答案:

答案 0 :(得分:1)

您尝试初始化通用类型,这是错误的,因为您可以扩展此类型并且初始化将不正确

示例:

const instance = new Foo<Props, { otherRequiredProperty: string } & State>({ foo: '' });
cosnt otherProperty = instance.state.otherRequiredProperty

所以我说状态类型将具有2个必需的道具,但是在您的班级中,您仅用bar进行了初始化...

您可以根据需要创建带有所需道具和其他可选道具的界面

interface Props {
  foo: string;
}

interface State {
  bar: string;
  [key: string]: string;
}

export class Foo extends React.Component<Props, State> {
  constructor(props: Props) {
    super(props);
    this.state = {
      bar: '',
    };

    this.setState({
      anything: '', // no error
    }); 
  }
}

这不会引发错误,您仍然可以在状态中添加另一个属性

答案 1 :(得分:0)

尝试一下:

class Foo extends React.PureComponent<P, S> {
    state: State; //Add this line

    constructor(props: P) {
        super(props);

        this.state = { bar: "asd" };
    }
}

答案 2 :(得分:0)

@Juraj Kocan在他的回答中写道。造成此问题的原因是:

  

您尝试初始化通用类型,这是错误的,因为您可以扩展此类型并且初始化将不正确

与此同时,我发现我可以通过在构造函数中扩展状态来处理它:

interface Props {
    foo: string;
}
interface State {
    bar: string;
}
class Foo<
    P extends Props = Props,
    S extends State = State
> extends React.Component<P, S> {
    constructor(props: P) {
        super(props);

        this.state = { ...this.state, bar: "asd" };
    }
}

您也可以在没有构造函数的情况下执行此操作:

interface Props {
    foo: string;
}
interface State {
    bar: string;
}
class Foo<
    P extends Props = Props,
    S extends State = State
> extends React.Component<P, S> {
   state:S = { ...this.state, bar: "asd" };
}

后一种解决方案更好,因为在构造函数中传播this.state会使我使用immutability-helper的地方出现其他错误。在构造函数中的传播使TypeScript在immutability-helper的update()函数中无法跟踪索引属性。