angular/packages/forms/src
Dylan Hunn f18e1739b8 fix(forms): allow FormBuilder.group(...) to accept optional fields. (#46253)
Consider the case in which `FormBuilder` is used to construct a group with an optional field:

```
const controls = { name: fb.control('') };
const foo: FormGroup<{
  name: FormControl<string | null>;
  address?: FormControl<string | null>;
}> = fb.group<{
  name: FormControl<string | null>;
  address?: FormControl<string | null>;
}>(controls);
```

Today, with fully strict TypeScript settings, the above will not compile:

```
Types of property 'controls' are incompatible.
Type '{ name: FormControl<string | null>; address?: FormControl<FormGroup<SubFormControls> | null | undefined> | undefined; }' is not assignable to type '{ name: FormControl<string | null>; address?: FormGroup<SubFormControls> | undefined; }'.
```

Notice that the `fb.group(...)` is calculating the following type for address: `address?: FormControl<FormGroup<string|null>`. This is clearly wrong -- an extraneous `FormControl` has been added!

This is coming from the calculation of the result type of `fb.group(...)`. In the type definition, if we cannot detect the outer control type, [we assume it's just an unwrapped value, and automatically wrap it in `FormControl`](https://github.com/angular/angular/blob/14.0.0/packages/forms/src/form_builder.ts#L66).

Because the optional `{address?: FormControl<string|null>}` implicitly makes the RHS have type `FormControl<string|null>|undefined`, [the relevant condition is not satisfied](https://github.com/angular/angular/blob/14.0.0/packages/forms/src/form_builder.ts#L55). In particular, the condition expects just `FormGroup<T>`, not `FormGroup<T>|undefined`. So we assume `T` is a value type, and it gets wrapped with `FormControl`.

The solution is to add the cases where `undefined` is included in the union type when detecting which control `T` is (if any).

PR Close #46253
2022-06-06 10:14:19 -07:00
..
directives docs(forms): Amend the FormGroupDirective docs to indicate it also works with FormRecord. (#46235) 2022-06-06 10:11:15 -07:00
model fix(forms): Warn on FormControls that are constructed with both options and asyncValidators. 2022-05-19 15:49:02 -07:00
directives.ts perf(forms): make RadioControlRegistry class tree-shakable (#41126) 2021-03-16 09:35:14 -07:00
errors.ts refactor(forms): use shared RuntimeError class (#44398) 2022-01-06 23:43:19 +00:00
form_builder.ts fix(forms): allow FormBuilder.group(...) to accept optional fields. (#46253) 2022-06-06 10:14:19 -07:00
form_providers.ts perf(forms): make RadioControlRegistry class tree-shakable (#41126) 2021-03-16 09:35:14 -07:00
forms.ts revert "fix(forms): Value and RawValue should be part of the public API." (#46023) 2022-05-17 22:48:03 +00:00
util.ts refactor(forms): Split up model.ts. (#45217) 2022-03-01 19:49:31 +00:00
validators.ts docs(forms): remove the incorrect set value from previous commit (#45533) 2022-04-07 21:00:25 +00:00
version.ts docs: fix package name in version.ts files in different packages (#41208) 2021-05-10 10:26:34 -04:00