esimonenko
esimonenko

Reputation: 33

react typescript constructor state vs property

I have following typescript code:

interface Props extends WithStyles<typeof styles> { }

interface State {
  users: Array<User>;
}

class UsersTable extends React.Component<Props, State> {
  state = {users: []};

  componentWillMount() {
    fetch(`${apiUrl}/users`)
      .then(resp => resp.json())
      .then(users => {
        this.setState({users});
      });
  }

  render() {
    const {classes} = this.props;
    const {users} = this.state;

    if (!users.length) {
      return('...Loading');
    }

    return(
      <Paper className={classes.root}>
        <Table className={classes.table}>
          <TableHead>
            <TableRow>
              <TableCell>Id</TableCell>
            </TableRow>
          </TableHead>
          <TableBody>
            {users.map(u => (
              <TableRow key={u.Id}>
                <TableCell numeric>{u.Id}</TableCell>
              </TableRow>
            ))}
          </TableBody>
        </Table>
      </Paper>
    );
  }
}
export default withRoot(withStyles(styles)(UsersTable));

Its won't compile with error: property 'Id' does not exist on type 'never'. As i understand this.state.users get type 'never', However if i add constructor:

  constructor(props: Props) {
    super(props);
    this.state = {users: []};
  }

It's compile just fine and state got correct type. So what's the difference between first approach and second one ?

Upvotes: 3

Views: 1416

Answers (1)

erikkallen
erikkallen

Reputation: 34401

The problem is that when you have the assignment state = {...} in the class, the type of state is determined by the type of whatever you assign state to, rather than the base class definition. This meas that the type of state here is {users: never[]} (though I thought it was any[], but that must be a difference in newer typescript versions).

Specify the type explicitly, eg. state: State = { users: [] }, or state = { users: [] } as State.

Upvotes: 4

Related Questions