Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(forms): Prevent FormBuilder from distributing unions to control types #45942

Closed
wants to merge 1 commit into from

Commits on May 10, 2022

  1. fix(forms): Prevent FormBuilder from distributing unions to control t…

    …ypes.
    
    Previously, using `FormBuilder` with a union type would produce unions of *controls*:
    
    ```
    // `foo` has type `FormControl<string>|FormControl<number>`.
    const c = fb.nonNullable.group({foo: 'bar' as string | number});
    ```
    
    This actually works in many cases, due to how extraordinarily powerful Typescript's distributive types are (e.g. `value` still has type `string|number`), but it is subtly incorrect. Here is a code example that exposes the reason the inference is incorrect. It exploits the fact that Typescript will not "un-distribute" a type, producing an obviously spurious error:
    
    ```
    // fc gets an inferred distributive union type `FormControl<string> | FormControl<number>`
    let fc = c.controls.foo;
    // Error: Type 'FormControl<string | number>' is not assignable to type 'FormControl<string> | FormControl<number>'.
    fc = new FormControl<string|number>('', {initialValueIsDefault: true});
    ```
    
    Instead, we want the union to apply to the *values*:
    
    ```
    // `foo` should have type `FormControl<string|number>`.
    const c = fb.nonNullable.group({foo: 'bar' as string | number});
    ```
    
    Essentially, we want to prevent Typescript from distributing the type. [As specified in the handbook](https://www.typescriptlang.org/docs/handbook/2/conditional-types.html#distributive-conditional-types):
    
    > Typically, distributivity is the desired behavior. To avoid that behavior, you can surround each side of the extends keyword with square brackets.
    
    This PR applies this suggestion to `FormBuilder`'s type inference.
    
    Fixes angular#45912.
    dylhunn committed May 10, 2022
    Configuration menu
    Copy the full SHA
    a2dfe80 View commit details
    Browse the repository at this point in the history