fix(forms): include null in .parent of abstract control (#32671)

It's perfectly valid for an abstract control not to have a defined parent; yet previously the
types were asserting that AbstractControl#parent is not a null value. This changes correctly
reflects the run-time behavior through the types.

BREAKING CHANGE: Type of AbstractFormControl.parent now includes null

`null` is now included in the types of .parent. If you don't already have a check for this case,
the TypeScript compiler might compain. A v11 migration exists which adds the not-null assertion
operator where necessary.

In an unlikely case your code was testing the parnet against undefined with sitrct equality,
you'll need to change this to `=== null` instead, since the parent is not explicily initialized
with `null` instead of being left `undefined`.

Fixes #16999

PR Close #32671
This commit is contained in:
lazarljubenovic 2019-09-13 17:17:18 +02:00 committed by Joey Perrott
parent 4beaddcb83
commit f4f1bcc997
2 changed files with 4 additions and 5 deletions

View File

@ -6,7 +6,7 @@ export declare abstract class AbstractControl {
get enabled(): boolean;
readonly errors: ValidationErrors | null;
get invalid(): boolean;
get parent(): FormGroup | FormArray;
get parent(): FormGroup | FormArray | null;
get pending(): boolean;
readonly pristine: boolean;
get root(): AbstractControl;

View File

@ -173,8 +173,7 @@ export abstract class AbstractControl {
// TODO(issue/24571): remove '!'.
_updateOn!: FormHooks;
// TODO(issue/24571): remove '!'.
private _parent!: FormGroup|FormArray;
private _parent: FormGroup|FormArray|null = null;
private _asyncValidationSubscription: any;
/**
@ -267,7 +266,7 @@ export abstract class AbstractControl {
/**
* The parent control.
*/
get parent(): FormGroup|FormArray {
get parent(): FormGroup|FormArray|null {
return this._parent;
}
@ -1018,7 +1017,7 @@ export abstract class AbstractControl {
*/
private _parentMarkedDirty(onlySelf?: boolean): boolean {
const parentDirty = this._parent && this._parent.dirty;
return !onlySelf && parentDirty && !this._parent._anyControlsDirty();
return !onlySelf && !!parentDirty && !this._parent!._anyControlsDirty();
}
}