//BASIC TYPES DEFINED IN @angular/forms + rxjs/Observable type FormGroup = import("@angular/forms").FormGroup; type FormArray = import("@angular/forms").FormArray; type FormControl = import("@angular/forms").FormControl; type AbstractControl = import("@angular/forms").AbstractControl; type Observable = import("rxjs").Observable; type STATUS = "VALID" | "INVALID" | "PENDING" | "DISABLED"; //<- I don't know why Angular Team doesn't define it https://github.com/angular/angular/blob/7.2.7/packages/forms/src/model.ts#L15-L45) type STATUSs = STATUS | string; //<- string is added only becouse Angular base class use string insted of union type https://github.com/angular/angular/blob/7.2.7/packages/forms/src/model.ts#L196) //OVVERRIDE TYPES WITH STRICT TYPED INTERFACES + SOME TYPE TRICKS TO COMPOSE INTERFACE (https://github.com/Microsoft/TypeScript/issues/16936) interface AbstractControlTyped extends AbstractControl { // BASE PROPS AND METHODS COMMON TO ALL FormControl/FormGroup/FormArray readonly value: T; valueChanges: Observable; readonly status: STATUSs; statusChanges: Observable; get(path: Array | string): AbstractControlTyped | null; setValue(value: V extends T ? V : never, options?: { onlySelf?: boolean; emitEvent?: boolean }): void; patchValue(value: V extends Partial ? V : never, options?: { onlySelf?: boolean; emitEvent?: boolean }): void; reset(value?: V extends Partial ? V : never, options?: { onlySelf?: boolean; emitEvent?: boolean }): void; } interface FormControlTyped extends FormControl { // COPIED FROM AbstractControlTyped BECOUSE TS NOT SUPPORT MULPILE extends FormControl, AbstractControlTyped readonly value: T; valueChanges: Observable; readonly status: STATUSs; statusChanges: Observable; get(path: Array | string): AbstractControlTyped | null; setValue(value: V extends T ? V : never, options?: { onlySelf?: boolean; emitEvent?: boolean }): void; patchValue(value: V extends Partial ? V : never, options?: { onlySelf?: boolean; emitEvent?: boolean }): void; reset(value?: V extends Partial ? V : never, options?: { onlySelf?: boolean; emitEvent?: boolean }): void; } interface FormGroupTyped extends FormGroup { // PROPS AND METHODS SPECIFIC OF FormGroup //controls: { [P in keyof T | string]: AbstractControlTyped

}; controls: { [P in keyof T]: AbstractControlTyped }; registerControl

(name: P, control: AbstractControlTyped): AbstractControlTyped; registerControl(name: string, control: AbstractControlTyped): AbstractControlTyped; addControl

(name: P, control: AbstractControlTyped): void; addControl(name: string, control: AbstractControlTyped): void; removeControl(name: keyof T): void; removeControl(name: string): void; setControl

(name: P, control: AbstractControlTyped): void; setControl(name: string, control: AbstractControlTyped): void; contains(name: keyof T): boolean; contains(name: string): boolean; get

(path: P): AbstractControlTyped; getRawValue(): T & { [disabledProp in string | number]: any }; // COPIED FROM AbstractControlTyped BECOUSE TS NOT SUPPORT MULPILE extends FormGroup, AbstractControlTyped readonly value: T; valueChanges: Observable; readonly status: STATUSs; statusChanges: Observable; get(path: Array | string): AbstractControlTyped | null; setValue(value: V extends T ? V : never, options?: { onlySelf?: boolean; emitEvent?: boolean }): void; patchValue(value: V extends Partial ? V : never, options?: { onlySelf?: boolean; emitEvent?: boolean }): void; reset(value?: V extends Partial ? V : never, options?: { onlySelf?: boolean; emitEvent?: boolean }): void; } interface FormArrayTyped extends FormArray { // PROPS AND METHODS SPECIFIC OF FormGroup controls: AbstractControlTyped[]; at(index: number): AbstractControlTyped; push(ctrl: AbstractControlTyped): void; insert(index: number, control: AbstractControlTyped): void; setControl(index: number, control: AbstractControlTyped): void; getRawValue(): T[]; // COPIED FROM AbstractControlTyped BECOUSE TS NOT SUPPORT MULPILE extends FormArray, AbastractControlTyped readonly value: T[]; valueChanges: Observable; readonly status: STATUSs; statusChanges: Observable; get(path: Array | string): AbstractControlTyped | null; setValue(value: V extends T[] ? V : never, options?: { onlySelf?: boolean; emitEvent?: boolean }): void; patchValue(value: V extends Partial[] ? V : never, options?: { onlySelf?: boolean; emitEvent?: boolean }): void; reset(value?: V extends Partial[] ? V : never, options?: { onlySelf?: boolean; emitEvent?: boolean }): void; }