Skip to content

Commit 7dc954f

Browse files
author
c-krzysztof.brilla
committed
fix: incorrect typing of FormArray value for complex models
1 parent 455aada commit 7dc954f

File tree

2 files changed

+116
-59
lines changed

2 files changed

+116
-59
lines changed

libs/reactive-forms/src/lib/form-array.spec.ts

Lines changed: 63 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,48 @@
11
import { Validators } from '@angular/forms';
22
import { expectTypeOf } from 'expect-type';
33
import { Observable, of, Subject, Subscription } from 'rxjs';
4-
import { FormControl, FormGroup } from '..';
4+
import {ControlsOf, FormControl, FormGroup, ValuesOf} from '..';
55
import { ControlState } from './core';
66
import { FormArray } from './form-array';
77

88
type Base = {
99
name: string;
10+
nameControl: FormControl<string>;
1011
phone: {
1112
prefix: string;
1213
number: string;
1314
};
15+
phoneControl: FormControl<{
16+
prefix: string;
17+
number: string;
18+
}>;
19+
phoneGroup: FormGroup<ControlsOf<{
20+
prefix: string;
21+
number: string;
22+
}>>
23+
deep: Base[];
24+
deepFormArray: FormArray<Base>;
1425
};
1526

27+
type ValueOfBase = {
28+
name: string;
29+
nameControl: string;
30+
phone: {
31+
prefix: string;
32+
number: string;
33+
};
34+
phoneControl:{
35+
prefix: string;
36+
number: string;
37+
};
38+
phoneGroup:{
39+
prefix: string;
40+
number: string;
41+
};
42+
deep: ValueOfBase[];
43+
deepFormArray: ValueOfBase[];
44+
}
45+
1646
describe('FormArray Types', () => {
1747
it('should infer primitives', () => {
1848
const arr = new FormArray<string>([new FormControl('')]);
@@ -56,26 +86,48 @@ describe('FormArray Types', () => {
5686
const arr = new FormArray<Base>([
5787
new FormGroup({
5888
name: new FormControl(''),
89+
nameControl: new FormControl(''),
5990
phone: new FormGroup({
6091
prefix: new FormControl(''),
6192
number: new FormControl(''),
6293
}),
94+
phoneControl: new FormControl({
95+
prefix: '',
96+
number: '',
97+
}),
98+
phoneGroup: new FormGroup({
99+
prefix: new FormControl(''),
100+
number: new FormControl(''),
101+
}),
102+
deep: new FormArray([]),
103+
deepFormArray: new FormArray([]),
63104
}),
64105
]);
65106

66-
expectTypeOf(arr.value).toEqualTypeOf<Base[]>();
67-
expectTypeOf(arr.valueChanges).toEqualTypeOf<Observable<Base[]>>();
68-
expectTypeOf(arr.value$).toEqualTypeOf<Observable<Base[]>>();
107+
expectTypeOf(arr.value).toEqualTypeOf<ValueOfBase[]>();
108+
expectTypeOf(arr.valueChanges).toEqualTypeOf<Observable<ValueOfBase[]>>();
109+
expectTypeOf(arr.value$).toEqualTypeOf<Observable<ValueOfBase[]>>();
69110

70111
// @ts-expect-error - should be typed
71112
arr.insert(0, new FormControl(1));
72113
arr.push(
73114
new FormGroup({
74115
name: new FormControl(''),
116+
nameControl: new FormControl(''),
75117
phone: new FormGroup({
76118
prefix: new FormControl(''),
77119
number: new FormControl(''),
78120
}),
121+
phoneControl: new FormControl({
122+
prefix: '',
123+
number: '',
124+
}),
125+
phoneGroup: new FormGroup({
126+
prefix: new FormControl(''),
127+
number: new FormControl(''),
128+
}),
129+
deep: new FormArray([]),
130+
deepFormArray: new FormArray([]),
79131
})
80132
);
81133

@@ -90,7 +142,7 @@ describe('FormArray Types', () => {
90142
);
91143

92144
const first$ = arr.select((state) => {
93-
expectTypeOf(state).toEqualTypeOf<Base[]>();
145+
expectTypeOf(state).toEqualTypeOf<ValueOfBase[]>();
94146

95147
return state[0];
96148
});
@@ -100,19 +152,19 @@ describe('FormArray Types', () => {
100152
// @ts-expect-error - should be typed
101153
arr.reset({ foo: '' });
102154

103-
arr.reset([{ name: '', phone: { prefix: '', number: '' } }]);
155+
arr.reset([{ name: '', phone: { prefix: '', number: '' }, nameControl: '', phoneControl: { prefix: '', number: '' }, phoneGroup: { prefix: '', number: '' }, deep: [], deepFormArray: [] }]);
104156

105-
expectTypeOf(arr.getRawValue()).toEqualTypeOf<Base[]>();
157+
expectTypeOf(arr.getRawValue()).toEqualTypeOf<ValueOfBase[]>();
106158
});
107159

108160
it('should infer setValue', () => {
109161
const arr = new FormArray<Base>([]);
110162

111163
try {
112-
arr.setValue([{ name: '', phone: { number: '', prefix: '' } }]);
164+
arr.setValue([{ name: '', phone: { prefix: '', number: '' }, nameControl: '', phoneControl: { prefix: '', number: '' }, phoneGroup: { prefix: '', number: '' }, deep: [], deepFormArray: [] }]);
113165

114166
const sub = arr.setValue(
115-
of([{ name: '', phone: { number: '', prefix: '' } }])
167+
of([{ name: '', phone: { prefix: '', number: '' }, nameControl: '', phoneControl: { prefix: '', number: '' }, phoneGroup: { prefix: '', number: '' }, deep: [], deepFormArray: [] }])
116168
);
117169
expectTypeOf(sub).toEqualTypeOf<Subscription>();
118170
} catch {
@@ -211,7 +263,7 @@ describe('FormArray Functionality', () => {
211263
});
212264

213265
it('should invalidChanges$', () => {
214-
const control = new FormArray([new FormControl(null, Validators.required)]);
266+
const control = new FormArray([new FormControl<string | null>(null, Validators.required)]);
215267
const spy = jest.fn();
216268
control.invalid$.subscribe(spy);
217269
expect(spy).toHaveBeenCalledWith(true);
@@ -222,7 +274,7 @@ describe('FormArray Functionality', () => {
222274
});
223275

224276
it('should validChanges$', () => {
225-
const control = new FormArray([new FormControl(null, Validators.required)]);
277+
const control = new FormArray([new FormControl<string | null>(null, Validators.required)]);
226278
const spy = jest.fn();
227279
control.valid$.subscribe(spy);
228280
expect(spy).toHaveBeenCalledWith(false);

0 commit comments

Comments
 (0)