TL;DR: The way TypeScript identifies its "types" mostly due to interfaces and context. My recommendation to solve the use is to explicitly create an interface and pass it to the form as it cannot be inferred.
In most cases; Angular will infer the form type as long as its initialized with the proper types in declaration. This answer acknowledged that specific use case.
Note about inferred types, inferred types require more work for refactorization. Also, interfaces you can be used to easily identify the object and attribute types by just looking its declaration, the later cannot be done using inferred types. Is my recommendation to always prefer interfaces over inferred types, of course this note comes from my own experience.
Your use case:
In the example you provided, there's no way way to infer the form
type, you've to explicitly tell. I've made this working example of a typed form. The official documentation you included in your question kind of already gives you most of the answer.
To remove the <any>
you see in your autocomplete, just implement your own interface:
export interface IMainForm {
title: FormControl<string>;
content: FormControl<string>;
}
public form!: FormGroup<IMainForm>; // <--- Use your interface
Also, your implementation of this.formBuilder.group
is deprecated because is not typesafe. You'll need to use the overload with AbstractControlOptions
instead (not the array one).
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)
});
}
As you can see in the following image, with those changes you'll see the typed value {Partial<{ title: string; content: string; }>}
.
You can check how type inference works for more detail in typescriptlang, here´s a small extract:
Simple type let x = 4
being number
The type of the x variable is inferred to be number. The kind of inference takes place when initializing variables and
members, setting parameter default values, and determining function
return types.
Best common type let x = [0, 1, null]
being of type (number | null)[]
To infer the type of x in the example above, we must consider the type
of each array element. Here we are given two choices for the type of
the array: number and null. The best common type algorithm considers
each candidate type, and picks the type that is compatible with all
the other candidates.
Contextual types window.onmousedown = function (mouseEvent) { ... }
, being MouseEvent
Contextual typing applies in many cases. Common cases include
arguments to function calls, right hand sides of assignments, type
assertions, members of object and array literals, and return
statements. The contextual type also acts as a candidate type in best
common type.
this.formBuilder.nonNullable.group
and it seems to work fine – Lissotrichous