I\'m creating a generic function to change the state.
The error message:
TS2345: Argument of type \'() => { [x:string]: string }\' is not assignable
There are a few solutions:
this.setState<never>({ [name]: value } as Partial<IInputStates>)
Or
this.setState({ [name]: value } as Pick<IInputStates, keyof IInputStates>);
There is an open issue in git, take a look: cannot setState with dynamic key name type-safe
Using types won't prevent the errors property from being changed as the type checking applies at compile time only. This will still run as plain old dynamic JavaScript when it gets to the browser where anything goes.
If you want to restrict the properties the change function acts on you need to check the property name e.g. against an array of allowed values.
As a side note your inputs are missing the name
property.
render() {
const { url, errors } = this.state;
return (
<form>
<input type="text" name="url" value={url} onChange={this.change} />
<input type="text" name="name" value={name} onChange={this.change} />
<form>
)
}
change = (event:React.ChangeEvent<HTMLInputElement>) => {
const name = event.target.name;
const value = event.target.value;
if (!isValidProperty(name)) return;
this.setState({ [name]: value } as Partial<IInputStates>)
}
// Dummy instance to force a compile warning and ensure we capture all the property names
const inputExample: IInputStates = { url: '' };
const inputKeys = Object.keys(inputExample);
function isValidProperty(name: string): name is keyof IInputStates {
return inputKeys.includes(name);
}