allow typescript compiler to call setState on only one react state property

前端 未结 5 2062
半阙折子戏
半阙折子戏 2020-12-13 06:17

I\'m using Typescript with React for a project. The Main component gets passed state with this interface.

interface MainState {
  todos: Todo[];
  hungry: B         


        
相关标签:
5条回答
  • 2020-12-13 06:43

    Edit: DO NOT USE this solution, prefer https://stackoverflow.com/a/41828633/1420794 See comments for details.

    Now that spread operator has shipped in TS, my preferred solution is

    this.setState({...this.state, editorState}); // do not use !
    
    0 讨论(0)
  • 2020-12-13 06:47

    I think that the best way to do it is to use Partial

    Declare your component in the following way

    class Main extends React.Component<MainProps, Partial<MainState>> {
    }
    

    Partial automatically changes all of the keys to optional.

    0 讨论(0)
  • 2020-12-13 06:55

    Update state explicitly, example with the counter

    this.setState((current) => ({ ...current, counter: current.counter + 1 }))
    
    0 讨论(0)
  • 2020-12-13 06:58

    Edit

    The definitions for react were updated and the signature for setState are now:

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

    Where Pick<S, K> is a built-in type which was added in Typescript 2.1:

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

    See Mapped Types for more info.
    If you still have this error then you might want to consider updating your react definitions.

    Original answer:

    I'm facing the same thing.

    The two ways I manage to get around this annoying issue are:

    (1) casting/assertion:

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

    (2) declaring the interface fields as optional:

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

    If anyone has a better solution I'd be happy to know!


    Edit

    While this is still an issue, there are two discussions on new features that will solve this problem:
    Partial Types (Optionalized Properties for Existing Types)
    and
    More accurate typing of Object.assign and React component setState()

    0 讨论(0)
  • 2020-12-13 07:04

    We can tell setState which field it should expect, by parametrising it with <'editorState'>:

    this.setState<'editorState'>({
      editorState: editorState
    });
    

    If you are updating multiple fields, you can specify them like this:

    this.setState<'editorState' | 'hungry'>({
      editorState: editorState,
      hungry: true,
    });
    

    although it will actually let you get away with specifying only one of them!

    Anyway with the latest TS and @types/react both of the above are optional, but they lead us to...


    If you want to use a dynamic key, then we can tell setState to expect no fields in particular:

    this.setState<never>({
      [key]: value,
    });
    

    and as mentioned above, it doesn't complain if we pass an extra field.

    (GitHub issue)

    0 讨论(0)
提交回复
热议问题