angular 非空的FormControl可以分配给可空的FormControl,导致误导性的类型安全性,

3qpi33ja  于 3个月前  发布在  Angular
关注(0)|答案(6)|浏览(42)

哪个@angular/*包是bug的来源?

forms

这是一个回归吗?

是的

描述

用例:一个输入类型为 FormControl<boolean | null> 的组件。用户可以分配一个 FormControl<boolean> 。组件可以在内部将值设置为null。用户在运行时收到意外的值,但没有编译错误。

const nonNullable = new FormControl(false, {nonNullable: true});
const nullable: FormControl<boolean | null> = nonNullable;
nullable.setValue(null); // nonNullable control receives value null which it does not expect;

默认情况下,TypeScript 不处理协变/限制协变。TypeScript 4.7引入了协变注解。将FormControl中的TValue标记为invariant解决了我在复现测试中遇到的问题。但是我不知道这个更改在Angular中会产生的所有影响。

请提供一个链接,指向最小复现bug的情况

https://stackblitz.com/edit/angular-ivy-ntzwtb?file=src/app/app.component.ts

请提供您看到的异常或错误

The error is: no compile time error for assigning the nonNullable control.

请提供您发现此bug的环境(运行 ng version )

Angular CLI: 14.2.2
Node: 18.13.0 (Unsupported)
Package Manager: npm 9.1.2
OS: win32 x64

Angular: 14.2.1
... animations, cdk, common, compiler, compiler-cli, core, forms
... language-service, material, platform-browser
... platform-browser-dynamic, router

Package                         Version
---------------------------------------------------------
@angular-devkit/architect       0.1402.2
@angular-devkit/build-angular   14.2.2
@angular-devkit/core            14.2.2
@angular-devkit/schematics      14.2.2
@angular/cli                    14.2.2
@schematics/angular             14.2.2
ng-packagr                      14.2.1
rxjs                            7.5.6
typescript                      4.8.3

还有其他信息吗?

  • 无响应*
2hh7jdfx

2hh7jdfx1#

nonNullable 在其设置为初始值的 constructor 之外没有运行时影响。
正如您可以通过这个有效的单元测试看到的那样:

it('supports invariance', () => {
      const nonNullableCtrl = new FormControl(false, {nonNullable: true});
      expect(nonNullableCtrl.valid).toBe(true); // OK

      const nullableCtrl: FormControl<boolean | null> = nonNullableCtrl;
      nullableCtrl.setValue(null); 

      expect(nullableCtrl.valid).toBe(true); // ok
      expect(nullableCtrl.value).toBe(null); // ok
    })
  });

我不确定这个功能是否受欢迎。

wnrlj8wa

wnrlj8wa2#

你好,Matthieu,

非常感谢你的快速回复。我现在有些困惑。你的代码片段中的这两行确实实现了我所要求的功能。

//@ts-expect-error nonNullable can't be assign to nullable.
const nullableCtrl: FormControl<boolean | null> = nonNullableCtrl;

ts-expect-error注解(以及这个测试通过的假设)告诉我们,在你的设置中,它的行为就像我希望它在我设置中那样。将一个非空控件分配给一个可空控件应该是不可能的。但在我的项目和复现堆栈blitz中,它是可以分配的。请参阅复现示例中的第17行。这正是我的问题所在。虽然可以分配,但我认为它不应该这样。
我不期望有任何运行时检查。我只是希望编译器不要告诉我一切都没问题;)

alen0pnh

alen0pnh3#

抱歉,我禁用了评论功能。我确实尝试了你的解决方案,它运行良好(顺便说一下,它没有破坏仓库中的任何单元测试)。除此之外,我的评论仍然有效。
对我来说,这取决于类型定义,只有类型定义决定了你期望的行为,所以对我来说,这更多是一个功能问题而不是一个问题。
我会让维护者回来提出一个“官方”的答案/决定。

xn1cxnb4

xn1cxnb44#

我仍然想知道为什么测试编译通过。如果有一个ts-expect-error注解,但编译器在下一行没有检测到错误,那么这种组合本身应该导致错误,对吗?

zpf6vheq

zpf6vheq5#

正如我所说,我在实现这个测试之前确实实现了你的不变式(in out T)解决方案。这就是为什么它起作用了!
顺便说一下,我不知道这个功能,感谢提醒!

zbq4xfa0

zbq4xfa06#

关于这个问题有什么新消息吗?

相关问题