@@ -15,11 +15,19 @@ import {FormArray, UntypedFormArray} from './model/form_array';
1515import { FormControl , FormControlOptions , FormControlState , UntypedFormControl } from './model/form_control' ;
1616import { FormGroup , UntypedFormGroup } from './model/form_group' ;
1717
18- function isAbstractControlOptions ( options : AbstractControlOptions |
19- { [ key : string ] : any } ) : options is AbstractControlOptions {
20- return ( < AbstractControlOptions > options ) . asyncValidators !== undefined ||
21- ( < AbstractControlOptions > options ) . validators !== undefined ||
22- ( < AbstractControlOptions > options ) . updateOn !== undefined ;
18+ function isAbstractControlOptions ( options : AbstractControlOptions | { [ key : string ] : any } | null |
19+ undefined ) : options is AbstractControlOptions {
20+ return ! ! options &&
21+ ( ( options as AbstractControlOptions ) . asyncValidators !== undefined ||
22+ ( options as AbstractControlOptions ) . validators !== undefined ||
23+ ( options as AbstractControlOptions ) . updateOn !== undefined ) ;
24+ }
25+
26+ function isFormControlOptions ( options : FormControlOptions | { [ key : string ] : any } | null |
27+ undefined ) : options is FormControlOptions {
28+ return ! ! options &&
29+ ( isAbstractControlOptions ( options ) ||
30+ ( options as FormControlOptions ) . initialValueIsDefault !== undefined ) ;
2331}
2432
2533/**
@@ -30,15 +38,25 @@ function isAbstractControlOptions(options: AbstractControlOptions|
3038 */
3139export type ControlConfig < T > = [ T | FormControlState < T > , ( ValidatorFn | ( ValidatorFn [ ] ) ) ?, ( AsyncValidatorFn | AsyncValidatorFn [ ] ) ?] ;
3240
33- // Disable clang-format to produce clearer formatting for this multiline type .
41+ // Disable clang-format to produce clearer formatting for these multiline types .
3442// clang-format off
35- export type ɵGroupElement < T > =
43+
44+ /**
45+ * FormBuilder accepts values in various container shapes, as well as raw values.
46+ * Element returns the appropriate corresponding model class.
47+ */
48+ export type ɵElement < T > =
3649 T extends FormControl < infer U > ? FormControl < U > :
3750 T extends FormGroup < infer U > ? FormGroup < U > :
3851 T extends FormArray < infer U > ? FormArray < U > :
3952 T extends AbstractControl < infer U > ? AbstractControl < U > :
4053 T extends FormControlState < infer U > ? FormControl < U | null > :
4154 T extends ControlConfig < infer U > ? FormControl < U | null > :
55+ // ControlConfig can be too much for the compiler to infer in the wrapped case. This is
56+ // not surprising, since it's practically death-by-polymorphism (e.g. the optional validators
57+ // members that might be arrays). Watch for ControlConfigs that might fall through.
58+ T extends Array < infer U | ValidatorFn | ValidatorFn [ ] | AsyncValidatorFn | AsyncValidatorFn [ ] > ? FormControl < U | null > :
59+ // Fallthough case: T is not a container type; use is directly as a value.
4260 FormControl < T | null > ;
4361
4462// clang-format on
@@ -57,13 +75,10 @@ export type ɵGroupElement<T> =
5775 */
5876@Injectable ( { providedIn : ReactiveFormsModule } )
5977export class FormBuilder {
60- group < T extends {
61- [ K in keyof T ] : FormControlState < any > | ControlConfig < any > | FormControl < any > | FormGroup < any > |
62- FormArray < any > | AbstractControl < any > | T [ K ]
63- } > (
78+ group < T extends { } > (
6479 controls : T ,
6580 options ?: AbstractControlOptions | null ,
66- ) : FormGroup < { [ K in keyof T ] : ɵGroupElement < T [ K ] > } > ;
81+ ) : FormGroup < { [ K in keyof T ] : ɵElement < T [ K ] > } > ;
6782
6883 /**
6984 * @description
@@ -124,12 +139,14 @@ export class FormBuilder {
124139 updateOn = options . updateOn != null ? options . updateOn : undefined ;
125140 } else {
126141 // `options` are legacy form group options
127- validators = options [ 'validator' ] != null ? options [ 'validator' ] : null ;
128- asyncValidators = options [ 'asyncValidator' ] != null ? options [ 'asyncValidator' ] : null ;
142+ validators = ( options as any ) [ 'validator' ] != null ? ( options as any ) [ 'validator' ] : null ;
143+ asyncValidators =
144+ ( options as any ) [ 'asyncValidator' ] != null ? ( options as any ) [ 'asyncValidator' ] : null ;
129145 }
130146 }
131147
132- return new FormGroup ( reducedControls , { asyncValidators, updateOn, validators} ) ;
148+ // Cast to `any` because the inferred types are not as specific as Element.
149+ return new FormGroup ( reducedControls , { asyncValidators, updateOn, validators} ) as any ;
133150 }
134151
135152 control < T > ( formState : T | FormControlState < T > , opts : FormControlOptions & {
@@ -169,36 +186,10 @@ export class FormBuilder {
169186 control < T > (
170187 formState : T | FormControlState < T > ,
171188 validatorOrOpts ?: ValidatorFn | ValidatorFn [ ] | FormControlOptions | null ,
172- asyncValidator ?: AsyncValidatorFn | AsyncValidatorFn [ ] |
173- null ) : FormControl < T | null > | FormControl < T > {
189+ asyncValidator ?: AsyncValidatorFn | AsyncValidatorFn [ ] | null ) : FormControl {
174190 return new FormControl ( formState , validatorOrOpts , asyncValidator ) ;
175191 }
176192
177- array < T > (
178- controls : Array < FormControl < T > > ,
179- validatorOrOpts ?: ValidatorFn | ValidatorFn [ ] | AbstractControlOptions | null ,
180- asyncValidator ?: AsyncValidatorFn | AsyncValidatorFn [ ] | null ) : FormArray < FormControl < T > > ;
181-
182- array < T extends { [ K in keyof T ] : AbstractControl < any > } > (
183- controls : Array < FormGroup < T > > ,
184- validatorOrOpts ?: ValidatorFn | ValidatorFn [ ] | AbstractControlOptions | null ,
185- asyncValidator ?: AsyncValidatorFn | AsyncValidatorFn [ ] | null ) : FormArray < FormGroup < T > > ;
186-
187- array < T extends AbstractControl < any > > (
188- controls : Array < FormArray < T > > ,
189- validatorOrOpts ?: ValidatorFn | ValidatorFn [ ] | AbstractControlOptions | null ,
190- asyncValidator ?: AsyncValidatorFn | AsyncValidatorFn [ ] | null ) : FormArray < FormArray < T > > ;
191-
192- array < T extends AbstractControl < any > > (
193- controls : Array < AbstractControl < T > > ,
194- validatorOrOpts ?: ValidatorFn | ValidatorFn [ ] | AbstractControlOptions | null ,
195- asyncValidator ?: AsyncValidatorFn | AsyncValidatorFn [ ] | null ) : FormArray < AbstractControl < T > > ;
196-
197- array < T > (
198- controls : Array < FormControlState < T > | ControlConfig < T > | T > ,
199- validatorOrOpts ?: ValidatorFn | ValidatorFn [ ] | AbstractControlOptions | null ,
200- asyncValidator ?: AsyncValidatorFn | AsyncValidatorFn [ ] | null ) : FormArray < FormControl < T | null > > ;
201-
202193 /**
203194 * Constructs a new `FormArray` from the given array of configurations,
204195 * validators and options.
@@ -212,11 +203,12 @@ export class FormBuilder {
212203 *
213204 * @param asyncValidator A single async validator or array of async validator functions.
214205 */
215- array (
216- controls : any [ ] , validatorOrOpts ?: ValidatorFn | ValidatorFn [ ] | AbstractControlOptions | null ,
217- asyncValidator ?: AsyncValidatorFn | AsyncValidatorFn [ ] | null ) : FormArray {
206+ array < T > (
207+ controls : Array < T > , validatorOrOpts ?: ValidatorFn | ValidatorFn [ ] | AbstractControlOptions | null ,
208+ asyncValidator ?: AsyncValidatorFn | AsyncValidatorFn [ ] | null ) : FormArray < ɵElement < T > > {
218209 const createdControls = controls . map ( c => this . _createControl ( c ) ) ;
219- return new FormArray ( createdControls , validatorOrOpts , asyncValidator ) ;
210+ // Cast to `any` because the inferred types are not as specific as Element.
211+ return new FormArray ( createdControls , validatorOrOpts , asyncValidator ) as any ;
220212 }
221213
222214 /** @internal */
@@ -261,13 +253,16 @@ export class UntypedFormBuilder extends FormBuilder {
261253 controlsConfig : { [ key : string ] : any } ,
262254 options ?: AbstractControlOptions | null ,
263255 ) : UntypedFormGroup ;
256+
264257 /**
265- * @deprecated
258+ * @deprecated This API is not typesafe and can result in issues with Closure Compiler renaming.
259+ * Use the `FormBuilder#group` overload with `AbstractControlOptions` instead.
266260 */
267261 override group (
268262 controlsConfig : { [ key : string ] : any } ,
269263 options : { [ key : string ] : any } ,
270264 ) : UntypedFormGroup ;
265+
271266 override group (
272267 controlsConfig : { [ key : string ] : any } ,
273268 options : AbstractControlOptions | { [ key : string ] : any } | null = null ) : UntypedFormGroup {
0 commit comments