TL;DR: TypeScript mainly uses interfaces and context to identify its "types." To address the issue, I suggest explicitly creating an interface and passing it to the form since inference is not possible.
In most scenarios, Angular can infer the form type when initialized with correct types in declaration. This response addresses that specific case.
Note on inferred types: Inferred types require more effort for refactoring. Interfaces can easily denote object and attribute types just by looking at their declaration, which cannot be done with inferred types. From my experience, I recommend always using interfaces over inferred types.
Your scenario:
In the example provided, there's no way to deduce the type of the form
; you must specify it explicitly. I have created a working example of a typed form. The official documentation mentioned in your question already covers most of the solution.
To get rid of the <any>
in your autocomplete, implement your own interface:
export interface IMainForm {
title: FormControl<string>;
content: FormControl<string>;
}
public form!: FormGroup<IMainForm>; // <--- Use your interface
Moreover, your usage of this.formBuilder.group
has been deprecated because it lacks type safety. You should use the overload with AbstractControlOptions
instead (not the array).
private initializeForm(): void {
this.form = this.formBuilder.group({
title: new FormControl<string|null>(null, [Validators.required, Validators.minLength(3)]),
content: new FormControl<string|null>(null, Validators.required)
});
}
With these adjustments, you will see the typed value as
{Partial<{ title: string; content: string; }>}
.
https://i.stack.imgur.com/ghJIw.png
You can refer to type inference details on typescriptlang. Here's a brief excerpt:
Simple type let x = 4
, inferred as number
The type of the x variable is determined to be number. This type of inference occurs during variable initialization, setting parameter defaults, and establishing function return types.
Best common type let x = [0, 1, null]
, resulting in (number | null)[]
For inferring the type of x in the given example, each element in the array's type must be considered. We have two options for the array type: number and null. The best common type algorithm evaluates all candidate types and selects one compatible with all other candidates.
Contextual types window.onmousedown = function (mouseEvent) { ... }
, yielding MouseEvent
Contextual typing applies to various situations such as function call arguments, assignment right-hand sides, type assertions, object and array literal members, and return statements. The contextual type also contributes as a candidate type in determining the best common type.