允许 typescript 编译器仅在一个反应状态属性上调用 setState

新手上路,请多包涵

我在一个项目中使用 Typescript 和 React。 Main 组件通过此接口获得传递状态。

 interface MainState {
  todos: Todo[];
  hungry: Boolean;
  editorState: EditorState;  //this is from Facebook's draft js
}

但是,下面的代码(只是摘录)不会编译。

 class Main extends React.Component<MainProps, MainState> {
  constructor(props) {
    super(props);
    this.state = { todos: [], hungry: true, editorState: EditorState.createEmpty() };
  }
  onChange(editorState: EditorState) {
    this.setState({
      editorState: editorState
    });
  }
}

编译器抱怨说,在 onChange 方法中,我只尝试为一个属性设置状态,属性 todos 和属性 hungry 在类型中丢失 { editorState: EditorState;} 。换句话说,我需要在 onChange 函数中设置所有三个属性的状态才能使代码编译。为了编译,我需要做

onChange(editorState: EditorState){
  this.setState({
    todos: [],
    hungry: false,
    editorState: editorState
  });
}

但没有理由在代码中此时设置 todoshungry 属性。在 typescript/react 中仅对一个属性调用 setState 的正确方法是什么?

原文由 Leahcim 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 539
2 个回答

编辑

更新了 react 的定义,并且 setState 的签名现在是:

 setState<K extends keyof S>(state: Pick<S, K>, callback?: () => any): void;

其中 Pick<S, K> 是 Typescript 2.1 中添加的内置类型:

 type Pick<T, K extends keyof T> = {
    [P in K]: T[P];
}

有关详细信息,请参阅 映射类型

如果您仍然有此错误,那么您可能需要考虑更新您的反应定义。

原答案:

我面临着同样的事情。

我设法解决这个恼人问题的两种方法是:

(1) 铸造/断言:

 this.setState({
    editorState: editorState
} as MainState);

(2) 声明接口字段为可选:

 interface MainState {
    todos?: Todo[];
    hungry?: Boolean;
    editorState?: EditorState;
}

如果有人有更好的解决方案,我很高兴知道!


编辑

虽然这仍然是一个问题,但有两个关于将解决此问题的新功能的讨论:

部分类型(现有类型的可选属性)

更准确地键入 Object.assign 和 React 组件 setState()

原文由 Nitzan Tomer 发布,翻译遵循 CC BY-SA 3.0 许可协议

显式更新状态,例如计数器

this.setState((current) => ({ ...current, counter: current.counter + 1 }))

原文由 Alex Craft 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进