Angular’s documentation suggests defining both interfaces and a manually typed form model. But with TypeScript and recursive types, we can avoid duplication! 🚀

Define a generic type:

export type IToForm<T> = {
  [K in keyof T]: T[K] extends Array<infer U>
    ? FormArray<U extends object ? FormGroup<IToForm<U>> : FormControl<U>>
    : T[K] extends Date
    ? FormControl<T[K]>
    : T[K] extends object
    ? FormGroup<IToForm<T[K]>>
    : FormControl<T[K]>>;
};

Now, create automatically typed forms:

customerForm = new FormGroup<IToForm<Customer>>({
  id: new FormControl(''),
  email: new FormControl(''),
  firstName: new FormControl(''),
  lastName: new FormControl(''),
  addresses: new FormArray([]),
  preferences: new FormGroup({
    newsletter: new FormControl(false),
    language: new FormControl('en'),
  }),
});

✅ Benefits:
🔹 No key name errors.
🔹 Autocomplete in the editor.
🔹 Less repetitive code.
🔹 If you change the model, the entire code will be affected.

📢 Have you tried this approach in your Angular forms? 🚀

Author Of article : David Garcia Read full article