I have the following interface that allows to create an object with whatever key as long as the value is another object that contains the value and error properties:
interface FormFields {
[key: string]: {
value: string;
error: boolean;
};
}
Then I have the following function that based on the object that we pass in, it creates the type guard according to the keys contained by that object:
// Returns form fields object with type guard
const getFormFields = <T extends FormFields>(formFields: T) => formFields;
It works as expected if I put whatever key and assign as a value the object containing the value and error properties:
// Works as expected if i pass all the necessary properties
const formFields2 = getFormFields({
email: { value: 'user@gmail.com', error: false },
});
console.log(formFields2.email);
console.log(formFields2.password); // Property 'password' does not exist on type '{ email: { value: string; error: false; }; }'.ts(2339)
Also it fails as expected if I omit one of the properties that nested object should contain:
// Fails as expected if i don't pass error property
const formFields = getFormFields({
email: { value: 'user@gmail.com' }, // Property 'error' is missing in type '{ value: string; }' but required in type '{ value: string; error: boolean; }'.ts(2741)
});
But the problem comes when inside the nested objects I put any property other than value or error because TypeScript will accept it:
// But doesn't prevent of adding more properties
const formFields3 = getFormFields({
email: {
value: 'user@gmail.com',
error: false,
// I want typescript yelling an error when attempting to add
// any property other than value or error
extraProperty: "extra property shouldn't be allowed",
},
});
I understand that when we extend a type <T extends FormFields> we're not telling typescript that the generic T object will be the same than FormFields but we're telling that it should satisfy at least the FormFields structure. So I was wondering if there is any way by modifying the interface or the constraint to ensure that T contains objects with value and error properties and not any other.