打字稿' keyof'与react setState函数一起使用时,关键字会出错

时间:2018-06-06 08:10:35

标签: typescript

我使用react和typescript编写简单的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行编译,错误。

  

类型的参数&#39; {[x:string]:string; }&#39;不能分配给&#39; State |的参数((prevState:Readonly,props:Props)=&gt; State | Pick&#39;。       属性&#39;用户名&#39;类型&#39; {[x:string]:string; }&#39;

&#39;键&#39; this.onChange函数中的参数只允许使用&#39; username&#39;或者密码&#39;正如我所料。这意味着打字稿知道 typeof&#39; key&#39;参数必须是&#39; username&#39;或者密码&#39;。这是显而易见的,因为我将其定义为(key:State of key)。

但为什么在setState函数中,typeof&#39; key&#39;参数更改为普通字符串?

感谢。

3 个答案:

答案 0 :(得分:1)

试试这段代码:

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

答案 1 :(得分:1)

您已遇到known TypeScript bug,其中联合类型的计算属性已扩展为索引签名。对于TypeScript 3.0,看起来就像fixed一样,但这不确定。

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

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

我对React不熟悉,不知道setState()是否期待完整State,但要警告{ [key]: value }Partial<State>,因为它赢了&key #39; t包含两个键...而且TypeScript不会抓住它,因为this.setState({ [key]: value } as Partial<State>); 是一个联合类型。所以在运行时要小心。您可能希望将断言作为

import javax.validation.Validator;`
import org.apache.commons.lang3.StringUtils;`
import org.springframework.validation.Errors;`
importorg.springframework.validation.beanvalidation.CustomValidatorBean;`

public class MyValidator extends CustomValidatorBean {`
    public void myvalidate(Object target,Errors errors,String flag,Profile profile){
        super.validate(target,errors);
        if(StringUtils.isEmpty(profile.name())){
            errors.rejectValue("name", "NotBlank.profilereg.name", new Object[] { "name" }, "Missing Required Fields");
        }       

    }           

}

如果这会导致错误,那么您应该修复一个真正的错误。

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

答案 2 :(得分:0)

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

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

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

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