【问题标题】:Typescript 'keyof' keyword makes error when using with react setState functionTypescript 'keyof' 关键字在使用 react setState 函数时出错
【发布时间】:2018-11-15 20:10:16
【问题描述】:

我正在用 react 和 typescript 编写 Simple LoginForm。

interface State {
    username: string;
    password: string;
}

class LoginForm extends React.Component<Props, State> {
    readonly state: Readonly<State> = {
        username: '',
        password: ''
    }

    onChange = (key: keyof State) => (e: React.FormEvent<HTMLInputElement>) => {
        const value = e.currentTarget.value;
        this.setState({ [key]: value });  // error
    }

    render() {
        return (
            ...
            <TextField
                ...
                onChange={this.onChange('username')}
            />
            <TextField
                ...
                onChange={this.onChange('password')}
            />
            ...
        )
    }
}

Typescript 在 setState 行中编译失败,出现错误。

类型参数 '{ [x: string]: string; }' 不可分配给“State |”类型的参数((prevState: Readonly, props: Props) => State | Pick'. 类型 '{ [x: string]: string; 中缺少属性 'username' }'。

this.onChange 函数中的“key”参数只允许“用户名”或“密码”,如我所料。这意味着打字稿知道 typeof 'key' 参数必须是 'username' 或 'password'。这很明显,因为我将其定义为 (key: key of State)。

但是为什么在 setState 函数中,typeof 'key' 参数变成了普通字符串呢?

谢谢。

【问题讨论】:

    标签: typescript


    【解决方案1】:

    添加它作为替代方案,因为这解决了我的问题。

    似乎在设置状态 this.setState({prop: value}) 时,React TS 有时可以期待完整的 state@jcalz 对所选答案的推测。

    this.setState({
          ...this.state,
          [key]: value
    });
    

    有关此问题的最佳做法的更多信息,请点击此处: https://github.com/DefinitelyTyped/DefinitelyTyped/issues/26635

    【讨论】:

      【解决方案2】:

      试试这个代码:

      onChange = (key: keyof IState) => (event: React.FormEvent<HTMLInputElement>) => {
          this.setState({
            [key]: event.currentTarget.value
          } as Pick<IState, keyof IState>);
      }
      

      【讨论】:

        【解决方案3】:

        您遇到了known TypeScript bug,其中联合类型的计算属性被扩展为索引签名。 看起来对于 TypeScript 3.0,这将是 fixed,但这并不确定。

        您现在应该使用的解决方法是 assert 该对象是预期的类型:

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

        我对 React 不够熟悉,无法知道 setState() 是否期待完整的 State,但请注意 { [key]: value }Partial&lt;State&gt;,因为它不会同时包含键...和 ​​TypeScript不会抓住这个,因为key 是一个联合类型。所以在运行时要小心。您可能希望将断言作为

        this.setState({ [key]: value } as Partial<State>);
        

        如果这导致了错误,那么你应该修复它。

        希望对您有所帮助。祝你好运!

        【讨论】:

        • 谢谢。你节省了我的时间。
        猜你喜欢
        • 2021-04-21
        • 2021-12-06
        • 2019-06-24
        • 2018-12-26
        • 2017-01-21
        • 1970-01-01
        • 2016-07-29
        • 1970-01-01
        • 2021-07-26
        相关资源
        最近更新 更多