Невозможно присвоить "состояние", потому что это постоянное или свойство только для чтения

Когда я выполняю поиск по этой проблеме, я могу найти только те вопросы, которые изменяют this.state прямо где-то в this.state метода, а не используя this.setState(). Моя проблема в том, что я хочу установить начальное состояние в конструкторе следующим образом:

export default class Square extends React.Component<any, any> {
  constructor(props: any) {
    super(props);
    this.state = {
      active: false
    };
  }

  public render() {
    ...
  }
}

Приложение не может начать со следующей ошибки компиляции:

Cannot assign to 'state' because it is a constant or a read-only property

И это потому, что в определении React.Component мы имеем:

readonly state: null | Readonly<S>;

Поэтому я не знаю, как это сделать. Официальное учебное пособие по JS прямо присваивает this.state и говорит, что это приемлемый шаблон для этого в конструкторе, но я не могу понять, как это сделать с помощью TypeScript.

Ответ 1

Это, по-видимому, недавнее изменение в @types/react response, введенное в commit 542f3c0, которое работает не очень хорошо, учитывая тот факт, что TypScript не поддерживает назначение родительских полей readonly в производных конструкторах.

Я предлагаю вернуться к предыдущей версии @types/react. Версия 16.4.2 представляется последней, прежде чем произойдет неудачное изменение.

Вы можете привязать версию, удалив ^ в вашем package.json:

"devDependencies": {
  ...
  "@types/react": "16.4.2",

Также ознакомьтесь с обсуждением этого изменения на странице запроса на определенную типу github

Ответ 2

Прежде чем откатываться назад (как было предложено в ответ @torvin), прочитайте https://github.com/DefinitelyTyped/DefinitelyTyped/pull/26813#issuecomment-400795486.

Это не должно было быть регрессией - решение состоит в том, чтобы использовать state как свойство. Это лучше, чем предыдущий подход (state установки в конструкторе), потому что:

  • вам больше не нужен конструктор
  • вы не можете забыть инициализировать состояние (теперь это ошибка времени компиляции)

Например:

type Props {}

type State {
  active: boolean
}

export default class Square extends React.Component<Props, State> {
  public readonly state: State = {
    active: false
  }

  public render() {
    //...
  }
}

Другой подход:

type Props {}

const InitialState = {
  active: false
}

type State = typeof InitialState

export default class Square extends React.Component<Props, State> {
  public readonly state = InitialState

  public render() {
    //...
  }
}