Skip to content

Commit

Permalink
Merge pull request #167 from criskrzysiu/array-forms-typing-fixes
Browse files Browse the repository at this point in the history
fix:  incorrect typing of FormArray value for complex models
  • Loading branch information
NetanelBasal authored Aug 3, 2022
2 parents 455aada + 7dc954f commit d586c31
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 59 deletions.
74 changes: 63 additions & 11 deletions libs/reactive-forms/src/lib/form-array.spec.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,48 @@
import { Validators } from '@angular/forms';
import { expectTypeOf } from 'expect-type';
import { Observable, of, Subject, Subscription } from 'rxjs';
import { FormControl, FormGroup } from '..';
import {ControlsOf, FormControl, FormGroup, ValuesOf} from '..';
import { ControlState } from './core';
import { FormArray } from './form-array';

type Base = {
name: string;
nameControl: FormControl<string>;
phone: {
prefix: string;
number: string;
};
phoneControl: FormControl<{
prefix: string;
number: string;
}>;
phoneGroup: FormGroup<ControlsOf<{
prefix: string;
number: string;
}>>
deep: Base[];
deepFormArray: FormArray<Base>;
};

type ValueOfBase = {
name: string;
nameControl: string;
phone: {
prefix: string;
number: string;
};
phoneControl:{
prefix: string;
number: string;
};
phoneGroup:{
prefix: string;
number: string;
};
deep: ValueOfBase[];
deepFormArray: ValueOfBase[];
}

describe('FormArray Types', () => {
it('should infer primitives', () => {
const arr = new FormArray<string>([new FormControl('')]);
Expand Down Expand Up @@ -56,26 +86,48 @@ describe('FormArray Types', () => {
const arr = new FormArray<Base>([
new FormGroup({
name: new FormControl(''),
nameControl: new FormControl(''),
phone: new FormGroup({
prefix: new FormControl(''),
number: new FormControl(''),
}),
phoneControl: new FormControl({
prefix: '',
number: '',
}),
phoneGroup: new FormGroup({
prefix: new FormControl(''),
number: new FormControl(''),
}),
deep: new FormArray([]),
deepFormArray: new FormArray([]),
}),
]);

expectTypeOf(arr.value).toEqualTypeOf<Base[]>();
expectTypeOf(arr.valueChanges).toEqualTypeOf<Observable<Base[]>>();
expectTypeOf(arr.value$).toEqualTypeOf<Observable<Base[]>>();
expectTypeOf(arr.value).toEqualTypeOf<ValueOfBase[]>();
expectTypeOf(arr.valueChanges).toEqualTypeOf<Observable<ValueOfBase[]>>();
expectTypeOf(arr.value$).toEqualTypeOf<Observable<ValueOfBase[]>>();

// @ts-expect-error - should be typed
arr.insert(0, new FormControl(1));
arr.push(
new FormGroup({
name: new FormControl(''),
nameControl: new FormControl(''),
phone: new FormGroup({
prefix: new FormControl(''),
number: new FormControl(''),
}),
phoneControl: new FormControl({
prefix: '',
number: '',
}),
phoneGroup: new FormGroup({
prefix: new FormControl(''),
number: new FormControl(''),
}),
deep: new FormArray([]),
deepFormArray: new FormArray([]),
})
);

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

const first$ = arr.select((state) => {
expectTypeOf(state).toEqualTypeOf<Base[]>();
expectTypeOf(state).toEqualTypeOf<ValueOfBase[]>();

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

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

expectTypeOf(arr.getRawValue()).toEqualTypeOf<Base[]>();
expectTypeOf(arr.getRawValue()).toEqualTypeOf<ValueOfBase[]>();
});

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

try {
arr.setValue([{ name: '', phone: { number: '', prefix: '' } }]);
arr.setValue([{ name: '', phone: { prefix: '', number: '' }, nameControl: '', phoneControl: { prefix: '', number: '' }, phoneGroup: { prefix: '', number: '' }, deep: [], deepFormArray: [] }]);

const sub = arr.setValue(
of([{ name: '', phone: { number: '', prefix: '' } }])
of([{ name: '', phone: { prefix: '', number: '' }, nameControl: '', phoneControl: { prefix: '', number: '' }, phoneGroup: { prefix: '', number: '' }, deep: [], deepFormArray: [] }])
);
expectTypeOf(sub).toEqualTypeOf<Subscription>();
} catch {
Expand Down Expand Up @@ -211,7 +263,7 @@ describe('FormArray Functionality', () => {
});

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

it('should validChanges$', () => {
const control = new FormArray([new FormControl(null, Validators.required)]);
const control = new FormArray([new FormControl<string | null>(null, Validators.required)]);
const spy = jest.fn();
control.valid$.subscribe(spy);
expect(spy).toHaveBeenCalledWith(false);
Expand Down
Loading

0 comments on commit d586c31

Please sign in to comment.