here is my function, where i am trying to call a method using indexed signature
. it works if i added the function name manually. but how to call it using object notation. it requires for make dynamic calls.
createFormControl(formControls:PatientFormProps[]):void {
for (const control of formControls) {
const newPatientFormControl = new FormControl();
if (control.options.required) {
const value = { label: 'email' };
newPatientFormControl.setValidators([Validators.required, PatientFormService.formProps["email"]]);//works
newPatientFormControl.setValidators([Validators.required, PatientFormService.formProps[value.label]);//error
}
this.patientForm.addControl(control.key, newPatientFormControl);
}
console.log(this.patientForm);
}
error:
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ email: () => { error: boolean; }; }'.
No index signature with a parameter of type 'string' was found on type '{ email: () => { error: boolean; }; }'.ts(7053)
the method i am trying to call is here:
export class PatientFormService {
static formProps = {
"email": () => {
console.log('email control');
return { error: true };
}
}
}
Here is my try with typescript playground. where i am getting similar error:
UPDATE:
As such robby, i tried this:
createFormControl(formControls:PatientFormProps[]):void {
for (const control of formControls) {
const newPatientFormControl = new FormControl();
if (control.options.required) {
const { key } = { ...control };//getting only needed key
newPatientFormControl.setValidators([Validators.required, PatientFormService.formProps[key as const]]);//not works
}
this.patientForm.addControl(control.key, newPatientFormControl);
}
console.log(this.patientForm);
}
CodePudding user response:
You need to add a const
assertion:
export class PatientFormService {
static formProps = {
"email": () => {
console.log('email control');
return { error: true };
}
};
}
const value = { label: 'email' } as const;
PatientFormService.formProps[value.label]();
CodePudding user response:
Another way to do it would be to define a union type of all the allowed values, and then use that type to constrain the type of value
in your example ({ label: 'email' }
has the type { label: string }
).
Here's a utility type that does basically that:
type StaticMethodNames<T> = { [K in keyof T]: T[K] extends Function ? K : never }[keyof T]
Here's your simplified example on TS Playground, updated to use this method to resolve the "Element implicitly has an 'any' type" error message you were getting, and here's another TS Playground that's a little closer to the original code you had.