问题
How should I address the error message:
Failed to compile
/.../SoftwareLicenseCodes/index.tsx
(14,20): Type declaration of 'any' loses type-safety. Consider replacing it with a more precise type.
This error occurred during the build time and cannot be dismissed.
See the following code:
import * as React from 'react';
import './SoftwareLicenseCodes.css';
interface SoftwareLicenseCodesProps {
}
interface SoftwareLicenseCodesState {
count: string;
oneTimeUsage: boolean;
duration: string;
validFrom: string;
validTo: string;
distributor: string;
[key: string]: any;
}
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;
回答1:
Your code only sets either string or boolean values, so you could lock it down a bit more:
interface SoftwareLicenseCodesState {
count: string;
oneTimeUsage: boolean;
duration: string;
validFrom: string;
validTo: string;
distributor: string;
[key: string]: string|boolean;
// ------------^^^^^^^^^^^^^^
}
Alternately, if you want to have full type safety, you could remove the string index signature and write extra code that switches on the name of the input and then uses an explicit property name. That maximizes your use of type-checking, while (obviously) increasing code size/complexity:
function setNamed(target: SoftwareLicenseCodesState, name: string, value: string|boolean): SoftwareLicenseCodesState {
if (name === "oneTimeUsage") {
// Probably add assertion here that value is a boolean
target.oneTimeUsage = value as boolean;
} else {
// Probably add assertion here that value is a string
const strValue = value as string;
switch (name) {
case "count":
target.count = strValue;
break;
case "duration":
target.duration = strValue;
break;
case "validFrom":
target.validFrom = strValue;
break;
case "validTo":
target.validTo = strValue;
break;
case "distributor":
target.distributor = strValue;
break;
default:
// Failed assertion here
}
}
return target;
}
Then
this.setState(setNamed({}, name, value));
Clumsy as all get-out, but maximizes type-checking.
I really want to find a way for you to use index types, but with the name coming from the name
property of an input
element, I can't see how to do that without the switch
above. Which bothers me, because I seem to recall some uber-clever way of using keyof
to build a union type for the name...
回答2:
You can maybe disable this TSLint rule , though I don't know how safe it is :
interface SoftwareLicenseCodesState {
count: string;
oneTimeUsage: boolean;
duration: string;
validFrom: string;
validTo: string;
distributor: string;
// tslint:disable-next-line: no-any
[key: string]: any;
}
回答3:
Sometimes you need to use any
. For example when you override the intercept()
method of HttpInterceptor
class: https://angular.io/api/common/http/HttpInterceptor
I personnaly disable this rule. To do that, go into you tslint.json
file and comment this line:
// "no-any": true,
来源:https://stackoverflow.com/questions/52144901/typescript-failed-to-compile-because-type-declaration-of-any-loses-type-safety