reactjs - 打字稿通用状态更改函数类型转换错误
问题描述
我正在创建一个通用函数来更改状态。
错误信息:
TS2345: Argument of type '() => { [x:string]: string }' is not assignable to parameter of type 'IUserSignUpState | Pick<IUserSignUpState, "url" | "errors"> | ((prevState: Readonly<IUserSignUpState>, props: Readonly<IUserSignUpState>) => IUserSignUpState | Pick<...> | null) null'.
Type '() => { [x: string] string; }' is not assignable to type '(prevState: Readonly<IUserSignUpState>, props: Readonly<IUserSignUpState>) => IUserSignupState | Pick<IUserSignUpState>, "url" | "errors" | null'.
Type '{ [x: string]: string; }' is not assignable to type 'IUserSignUpState | Pick<IUserSignUpState, "url" | "errors"> | null'.
Type '{ [x: string]: string; }' is missing the following properties from type 'Pick<IUserSignUpState, "url" | "errors">': url, errors.
这是通用更改功能的示例:
./UserSignUp.tsx
interface IUserSignUpState {
url: string;
errors: string[];
// following can be used, but will lose type checking (*)
// [key: string]: string;
}
class UserSignUp extends React.Component<{}, IUserSignUpState>
state = {
url: '',
name: '',
errors: [],
};
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;
// gives error here:
this.setState(() => {
return {
[name]: value
}
})
}
};
在此示例中,更改事件应该只允许更新url: string;
andname: string;
和 not errors: []
。
我应该定义'url'和'name'类型并以某种方式在更改函数中重用它们吗?
*在 Typescript 文档中,它声明可以使用可索引类型。但是,这样做我将失去类型检查。副作用是我可能还设置了“错误”状态,这通常不应该通过更改功能实现。
更新:根据这个Stackoverflow Question中的答案,以下解决方案是可能的:
拆分界面:
interface IInputState {
url: string;
}
interface IUserSignUpState extends IInputState {
errors: string[];
}
并通过以下方式重新使用该接口:
this.setState({ [name]: value } as Partial<IInputStates>)
或者:
const name = event.target.name as keyof IInputStates;
const value = event.target.value;
this.setState(():IInputStates => {
return { [name]: value }
});
解决方案
使用类型不会阻止更改错误属性,因为类型检查仅适用于编译时。当它到达浏览器时,它仍将作为普通的旧动态 JavaScript 运行。
如果您想限制更改功能作用的属性,您需要检查属性名称,例如针对允许值的数组。
作为旁注,您的输入缺少该name
属性。
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);
}
推荐阅读
- python - 如何在python中解压嵌套数组
- windows - 对 Windows 的风景依赖?
- javascript - 我应该如何在 D3 中的 .data 之前替换这个 .selectAll ?
- javascript - 如果请求在 React 中是 GET,则无法从服务器获取响应
- java - Level Up & XP - 让代码更高效
- python - Python - Matplotlib 未在孪生图上显示任何轴标签
- angular - 如何在角度项目中更改基本网址
- javascript - JS在窗口重新加载后自动播放背景音频
- eclipse - Eclipse - 代码中显示的编译器错误。寻找偏好来删除它
- java - Java-Oracle - 无法创建特定表