Definitelytyped: 16.4.4 version introduced an issue with setting state in a constructor

Created on 28 Jun 2018  路  12Comments  路  Source: DefinitelyTyped/DefinitelyTyped

After updating typings to @types/ 16.4.4. we got set of these errors:
error TS2540: Cannot assign to 'state' because it is a constant or a read-only property.
The code that was broken:

constructor(props) {
        super(props);
        this.state = {
            stateProperty: initialValue
        }
    }

The fix is to use

constructor(props) {
        super(props);
        this.setState({
            stateProperty: initialValue
        });
    }

Previous version we used was @types/ 16.0.40
ReadOnly property should be allowed to set in a constructor.

Authors: @johnnyreilly, @bbenezech, @pzavolinsky, @digiguru, @ericanderson, @morcerf, @tkrotoff, @DovydasNavickas, @onigoetz, @theruther4d, @guilhermehubner, @ferdaber, @jrakotoharisoa

Most helpful comment

Yeah. v16.4.2 of the type definitions is still working fine when v16.4.4 just breaks a lot of existing codebase in my project.

All 12 comments

+1

Actually that is not a fix... https://github.com/DefinitelyTyped/DefinitelyTyped/pull/26813#issuecomment-400795486 is the correct fix

Yeah. v16.4.2 of the type definitions is still working fine when v16.4.4 just breaks a lot of existing codebase in my project.

+1

The fix I suggested is not entirely correct as it is stated here and the reason is React documentation

PRs welcome folks! Ping me and I'll review...

+1

+1.
The null here also introduce errors when using react redux connect().
state: null | Readonly<S>;

In summary, derived class loses the ability to declare a non-null state. strictNullChecks will expose the problem.

Please dont add the null back in the future. typings are tools to make life easier, not harder.

Consider a plain class:

class Apple {

    state: {taste: string};

    constructor() {
        this.state = {
            taste: "sweet",
        };
    }

    yearsLater(): void {
        console.log(this.state.taste);
    }
}

I can declare a non-null state and initialize it in my constructor. everything is fine.

Then turn it into a 16.4.4 react component.

class Apple extends React.Component<{}, {taste: string}> {
    constructor(props: Readonly<{}>) {
        super(props);
        this.state = {
            taste: "sweet",
        };
    }

    yearsLater(): void {
        console.log(this.state.taste); // [ts] Object is possibly 'null'
    }
}

I got a compile-time error. How to tell React.Component that my state is not null and I WILL initialize it in constructor ?

Let's use an example from react official doc: https://reactjs.org/docs/state-and-lifecycle.html

class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }

  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

How to write such code in typescript with strictNullChecks=true?

26945 contains a PR to fix this major issue

Fixed in 16.4.6

26946 fixed it. Thank you very much @Hotell, @ferdaber, and @johnnyreilly !

Was this page helpful?
0 / 5 - 0 ratings