虽然是在最新版本的Angular(版本14),似乎我没有做好的东西,因此 * 严格类型 * React形式没有工作的预期。
使用注入的FormBuilder
在ngOnInit
内初始化窗体。
public form!: FormGroup;
constructor(private formBuilder: FormBuilder) {}
ngOnInit(): void {
this.initializeForm();
}
private initializeForm(): void {
this.form = this.formBuilder.group({
title: ['', [Validators.required, Validators.minLength(3)]],
content: ['', Validators.required],
});
}
现在,当我尝试访问表单的控件时,没有自动完成,类型为FormGroup<any>
。而且,当尝试访问FormGroup
对象上不存在的控件时,它也不会抛出错误。
- 示例:
package.json
- Angular 官方文件:
3条答案
按热度按时间9rnv2umw1#
Angular文档还不够清楚,但是类型检查不适用于严格类型化的Reactive Form的原因是因为您正在OnInit钩子中初始化表单。
相反,你需要直接初始化你的表单,这样就可以推断出类型。如果你不这样做,只是给予它一个FormGroup类型,它默认为
FormGroup<any>
,这就是为什么你看不到Angular类型化表单的好处。您的示例应该可以像这样重构:
我已经添加了a working example,并包含了一行被注解掉的行,这行试图设置错误的类型,如果你取消注解它,你会看到一个类型错误,编辑器会警告你。
注意--我不想粗鲁,但是@luiscla27对这个问题的公认答案是错误的,对任何发现这个SO问题的人都没有帮助,因为他们遇到了一个常见的陷阱,即不像OP那样直接初始化他们输入的React形式。
hc2pp10m2#
这里有一个解决方案,它不需要您定义接口,而是使用推断的类型
j91ykkif3#
TL;DR:TypeScript识别其“类型”的方式主要是由界面和内容所决定。我建议解决这个问题的方法是明确建立界面,并将它传递给表单,因为它无法推断。
在大多数情况下; Angular将推断表单类型,只要它在声明中用正确的类型初始化。这个answer确认了那个特定的用例。
关于推断类型的注意事项,推断类型需要更多的重构工作。我的建议是始终优先选择接口而不是推断类型,当然,这条注意事项来自我自己的经验,可能会被我遗漏的一些东西所推翻。请随时告诉我,以便我可以相应地更新我的答案。
您的使用案例:
在你提供的例子中,没有办法推断出
form
的类型,你必须明确地告诉。我已经把this working example做成了一个类型化的表单。你在问题中包括的official documentation已经给了你大部分的答案。要删除自动完成中的
<any>
,只需实现自己的接口:第一个
此外,您的
this.formBuilder.group
实作已过时,因为不是类型安全的。您将需要改用AbstractControlOptions
的多载(而非数组)。如下图所示,通过这些更改,您将看到键入的值
{Partial<{ title: string; content: string; }>}
. x1c 0d1x你可以在typescriptlang中查看how type inference works以获得更多细节,这里有一个小的摘录:
let x = 4
为number
*x变数的型别会被推断为number。当初始化变数和成员、设定参数预设值,以及决定函数传回型别时,就会发生这种推断。
let x = [0, 1, null]
类型为(number | null)[]
*在上面的例子中,我们必须考虑每个数组元素的类型。下面我们给出了两种数组类型的选择:number和null。最佳通用类型算法考虑每个候选类型,并挑选与所有其他候选类型兼容的类型。
window.onmousedown = function (mouseEvent) { ... }
,即MouseEvent
*上下文类型在许多情况下都适用。常见的情况包括函数调用的参数、赋值语句的右侧、类型Assert、对象和数组文本的成员以及返回语句。上下文类型还可用作最佳通用类型中的候选类型。