I have two objects that handle errors in the form:
formErrors =
{
'firstname': '',
'lastname': '',
'telnum': '',
'email': ''
}
ValidationMessages = {
'firstname':{
'required': 'First name is required.',
'minlength': 'First name must be at least two characters long.',
'maxlength': 'First name must be at least twenty-five characters long.'
},
'lastname':{
'required': 'Last name is required.',
'minlength': 'Last name must be at least two characters long.',
'maxlength': 'Last name must be at least twenty-five characters long.'
},
'telnum':{
'required': 'Tel. number is required.',
'pattern': 'Tel. number must contain only numbers.'
},
'email':{
'required': 'Email is required.',
'email': 'Email not in valid format.'
}
}
Here is a validator using these objects:
onValueChanged(data?: any){
if (!this.feedbackForm) {return;}
const form = this.feedbackForm;
for (const field in this.formErrors){
if (this.formErrors.hasOwnProperty(field)) {
//clear previous error message (if any)
this.formErrors[field] = ''
const control = form.get(field);
if (control && control.dirty && !control.valid){
const messages = this.ValidationMessages[field];
for (const key in control.errors){
if (control.errors?.hasOwnProperty(key)){
this.formErrors[field] += messages[key] + ' ';
}
}
}
}
}
}
I've tried to get properties from my array object but I get the error: TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ firstname: string; lastname: string; telnum: string; email: string; }'. I need to type any ok
I've fixed this by typing my array with any, but I've got new errors like
I can't get any properties from here
Does someone know how to solve it?
When you assign an object to a variable, Typescript types it on-the-fly. Taking your
formErrorsobject for example, what you wrote is equivalent for Typescript to:As you can see, if you used that kind of typing for your object you wouldn't expect to access any other property than the 4 you declared in the
FormErrorsinterface. And that's what Typescript is telling you.When you try and access your object's property through a variable (
formErrors[field]), this variable could contain any possible string and not just the 4 keys allowed by your object's type. Typescript does not care that you're looping over the keys, that's only known to you at this point.You have two options when facing this error:
keyofoperator to tell Typescript that your variable is a valid keyIndexable types
You make a type indexable by saying "this object can contain any key" making it possible to use a string variable to access an object's property.
Applied to the
FormErrorsexample:Notice the line I've added before your properties: it's the index signature saying that
FormErrorscan contain a bunch of keys associated with string values. You could now writeformErrors['banana']and Typescript wouldn't say anything.Note that this signature can be used on its own, I've kept the properties because it lets you write things like
formErrors.lastname(instead offormErrors['lastname']) and get autocompletion.Here is a random article that will explain you more about indexable types.
keyofoperatorA better way to solve this in such cases where you know the exhaustive list of properties is to use the
keyofoperator to tell Typescript that your string variable can only contain a key that belongs to your type.A valid loop for the
FormErrorsinterface (without index signature) would be:Here is Typescript's documentation about
keyof, and here is another random article to know more about it.