簡體   English   中英

TypesScript錯誤地假定該屬性為只讀

[英]TypesScript wrongly assumes that property is read-only

我有一個使用打字稿創建的簡單反應組件,遇到以下奇怪的錯誤。 這是我的代碼。

interface State {
  value: string
}

class App extends React.Component<{}, State> {
  constructor() {
    super();
    this.state = {
      value: ''
    }
  }

  changeHandler = (e: any) => {
    let state = Object.assign({}, this.state);
    state.value = e.target.value;
    this.setState(state);
  }

  render() {
    return (
      <div className="App">
        <input
          type="text"
          value={this.state.value}
          name="value"
          onChange={this.changeHandler} />
      </div>
    );
  }
}

export default App;

這就是我得到的錯誤。

錯誤TS2540:不能分配到“價值”,因為它是一個常量或只讀屬性。

這個錯誤讓我想到也許這是打字稿執行不變異狀態規則的方式。 為了驗證這一理論,我做了以下工作。

this.state.value = e.target.value

在這種情況下,我顯然可以直接改變狀態,並且可以肯定地得到相同的錯誤。

然后我想到了將界面更改為此的想法。

interface State {
  value: Ivalue
}

interface Ivalue {
  value: string;
}

然后,我將組件重構為使用這種新接口。

class App extends React.Component<{}, State> {
  constructor() {
    super();
    this.state = {
      value: {
        value: ''
      }
    }
  }

  changeHandler = (e: any) => {
    let value = Object.assign({}, this.state.value);
    value.value = e.target.value;
    this.setState({value});
  }

  render() {
    return (
      <div className="App">
        <input
          type="text"
          value={this.state.value.value}
          name="value"
          onChange={this.changeHandler} />
      </div>
    );
  }
}

export default App;

當然可以編譯了! 我的問題確實是2個問題。 首先,為什么打字稿不滿意我的狀態副本,就像我在使用Object.assign第一段代碼中那樣? 第二,為什么將我的狀態對象嵌套更深一層來解決此問題?

如果Object.assign的內部實現(或其對TypeScript的理解)是復制對象成員的描述符,而不僅僅是字段名,則它復制的是state.valuereadonly屬性,而不僅僅是state.value

我不能保證這實際上發生了什么事,因為這將是我這個消息。 但這實際上是好消息,而不是壞消息。

您正在使用什么版本的事物?

另外,如果要在下一個主要版本中繼續使用setState的功能形式, setState養成使用它的習慣。

您可以將其重寫為:

changeHandler = (e: any) => {
    this.setState({value: e.target.value});
}

或具有解構作用

changeHandler = ({target: {value}}: any) => {
    this.setState({value});
}

在Typescript中,您可以將您的媒體資源標記為只讀。 是更好的方法,因為直接不可變狀態不是好的模式。 您必須運行setState()函數來更改狀態。

您的道具和狀態可能如下所示:

interface State {
   readonly value: string;
}

我用“只讀”標記類型中的所有屬性(用於props,state,redux等)。 我想要所有的東西都是不變的:)

如果查看React組件的類型定義,可以看到state屬性定義為Readonly<S> ,其中S是狀態類型參數。

https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/react/index.d.ts#L209

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM