本文介绍了TypeScript 抱怨我使用属性访问器的 setState 语句的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
在下面的代码示例中,我尝试为多个输入设置一个 onInputChange 处理程序,TypeScript 在语句 {[name]: value}
:
上给了我以下错误[ts]'{ [x: number]: string | 类型的参数布尔值;}' 不可分配给类型为 'SoftwareLicenseCodesState | 的参数((prevState: Readonly, props: Readonly) => SoftwareLicenseCodesState | Pick | null) |选择<...>|空值'.输入 '{ [x: number]: 字符串 |布尔值;}' 不可分配到类型 'Pick<SoftwareLicenseCodesState, "count" |"oneTimeUsage" |持续时间" |"validFrom" |有效到" |分销商">'.类型 '{ [x: number]: string | 中缺少属性 'count'布尔值;}'.
这里有什么问题?我该如何解决?
import * as React from 'react';导入'./SoftwareLicenseCodes.css';界面 SoftwareLicenseCodesProps {}界面 SoftwareLicenseCodesState {计数:字符串;oneTimeUsage:布尔值;持续时间:字符串;有效从:字符串;有效到:字符串;分配器:字符串;}类 SoftwareLicenseCodes 扩展了 React.Component{构造函数(道具:SoftwareLicenseCodesProps){超级(道具);this.state = {经销商:'',数数:'',oneTimeUsage:假,期间: '',有效发件人:'',有效: ''};this.onInputChange = this.onInputChange.bind(this);}handleSubmit(事件:React.FormEvent){警报('提交');event.preventDefault();}onInputChange = (事件: React.FormEvent) =>{const value = event.currentTarget.type === 'checkbox' ?event.currentTarget.checked : event.currentTarget.value;this.setState({[名称]:值});}使成为() {返回 (<div className="user-container software-codes"><div className="user-single-container"><h1>软件许可代码</h1><form className="software-codes__form" onSubmit={this.handleSubmit}><标签><span className="software-codes__input-element">计数</span><标签><span className="software-codes__input-element">分销商</span><标签><span className="software-codes__input-element">一次使用</span><标签><span className="software-codes__input-element">持续时间</span><input className="software-codes__input-element" type="submit" value="Submit"/></表单>
);}}导出默认的 SoftwareLicenseCodes;
解决方案
你没有显示错误抱怨的接口 (LicenseCodesState
, Pick
),但我假设它们的定义类似于您引用的 SoftwareLicenseCodesState
.
要允许像您的 this.setState({[name]: value});
这样的动态属性分配,您需要做以下两件事之一:
为定义添加动态属性访问(但请继续阅读):
interface SoftwareLicenseCodesState {计数:字符串;oneTimeUsage:布尔值;持续时间:字符串;有效从:字符串;有效到:字符串;分配器:字符串;[键:字符串]:任何;//<===}
手册将其称为字符串索引签名",它包含在接口一>.
问题在于,当然,这意味着您会丢失类型检查 —不仅在您使用它的地方,而且基本上在您使用 SoftwareLicenseCodesState
的任何地方.
在执行 setState
调用的地方使用类型断言.你有几个选择.您可以对 name
使用断言:
const name = event.currentTarget.name as keyof SoftwareLicenseCodesState;this.setState({[name]: value});
或在您传递的状态对象上:
this.setState({[event.currentTarget.name]: value} as Partial);
这会丢失对该调用的类型检查,但将其保留在其他地方.
In the code example below, where I try to have one onInputChange handler for several inputs, TypeScript gives me the following error on the statement {[name]: value}
:
[ts]
Argument of type '{ [x: number]: string | boolean; }' is not assignable to parameter of type 'SoftwareLicenseCodesState | ((prevState: Readonly<SoftwareLicenseCodesState>, props: Readonly<SoftwareLicenseCodesProps>) => SoftwareLicenseCodesState | Pick<SoftwareLicenseCodesState, "count" | ... 4 more ... | "distributor"> | null) | Pick<...> | null'.
Type '{ [x: number]: string | boolean; }' is not assignable to type 'Pick<SoftwareLicenseCodesState, "count" | "oneTimeUsage" | "duration" | "validFrom" | "validTo" | "distributor">'.
Property 'count' is missing in type '{ [x: number]: string | boolean; }'.
What is wrong here? How can I fix it?
import * as React from 'react';
import './SoftwareLicenseCodes.css';
interface SoftwareLicenseCodesProps {
}
interface SoftwareLicenseCodesState {
count: string;
oneTimeUsage: boolean;
duration: string;
validFrom: string;
validTo: string;
distributor: string;
}
class SoftwareLicenseCodes extends React.Component<SoftwareLicenseCodesProps, SoftwareLicenseCodesState> {
constructor(props: SoftwareLicenseCodesProps) {
super(props);
this.state = {
distributor: '',
count:'',
oneTimeUsage: false,
duration: '',
validFrom: '',
validTo: ''
};
this.onInputChange = this.onInputChange.bind(this);
}
handleSubmit(event: React.FormEvent<HTMLFormElement>) {
alert('submit');
event.preventDefault();
}
onInputChange = (event: React.FormEvent<HTMLInputElement>) => {
const value = event.currentTarget.type === 'checkbox' ? event.currentTarget.checked : event.currentTarget.value;
this.setState({
[name]: value
});
}
render() {
return (
<div className="user-container software-codes">
<div className="user-single-container">
<h1>Software License Codes</h1>
<form className="software-codes__form" onSubmit={this.handleSubmit}>
<label>
<span className="software-codes__input-element">Count</span>
<input
name="count"
type="number"
value={this.state.count}
/>
</label>
<label>
<span className="software-codes__input-element">Distributor</span>
<input
name="distributor"
type="text"
value={this.state.distributor}
/>
</label>
<label>
<span className="software-codes__input-element">One time usage</span>
<input
name="oneTimeUsage"
type="checkbox"
checked={this.state.oneTimeUsage}
/>
</label>
<label>
<span className="software-codes__input-element">Duration</span>
<input
name="duration"
type="number"
value={this.state.duration}
/>
</label>
<input className="software-codes__input-element" type="submit" value="Submit" />
</form>
</div>
</div>
);
}
}
export default SoftwareLicenseCodes;
解决方案
You haven't shown the interfaces the errors complain about (LicenseCodesState
, Pick
), but I'm going to assume they're defined similarly to your quoted SoftwareLicenseCodesState
.
To allow dynamic property assignment like your this.setState({[name]: value});
, you need to do one of two things:
Add dynamic property access to the definition (but keep reading):
interface SoftwareLicenseCodesState {
count: string;
oneTimeUsage: boolean;
duration: string;
validFrom: string;
validTo: string;
distributor: string;
[key: string]: any; // <===
}
The handbook calls this a "string index signature," it's covered under Interfaces.
The problem with this is that, of course, that means you lose type checking — not just where you use it, but basically anywhere you use SoftwareLicenseCodesState
.
Use a type assertion where you do the setState
call. You have a couple of options there. You can use an assertion on name
:
const name = event.currentTarget.name as keyof SoftwareLicenseCodesState;
this.setState({[name]: value});
or on the state object you're passing:
this.setState({[event.currentTarget.name]: value} as Partial<SoftwareLicenseCodesState>);
This loses type checking on that call, but preserves it elsewhere.
这篇关于TypeScript 抱怨我使用属性访问器的 setState 语句的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!