为啥 TypeScript 4 转译器没有看到这个不正确的类型传递给函数?

Posted

技术标签:

【中文标题】为啥 TypeScript 4 转译器没有看到这个不正确的类型传递给函数?【英文标题】:Why did TypeScript 4 transpiler not see this incorrect type passed to function?为什么 TypeScript 4 转译器没有看到这个不正确的类型传递给函数? 【发布时间】:2021-08-07 15:32:56 【问题描述】:

我有一个不同的问题,现在把我引到这里。

我原来的问题是这样的: Why is form: FormGroup showing 'controls' as undefined in an Angular11 component?

所以这块 (ngSubmit)="send(newMaterialFormGroup.value)"> 应该是 改为 (ngSubmit)="send(newMaterialFormGroup)">

这样做会传递对象,从而允许我访问控件 成功。

但问题仍然存在......

这是组件方面:

send(form: FormGroup): void
    let jsonModel = 
      materialNum: form.controls['materialNum'].value,
    ;

    let jsonModelRaw: string = JSON.stringify(jsonModel);
    //...

我正在使用"typescript": "~4.1.5"

如果我明确声明参数的类型为 FormGroup 并且我在 TypeScript 设置中启用了严格类型,为什么 TS 没有检测到这一点。

【问题讨论】:

newMaterialFormGroup的类型是什么? newMaterialFormGroup.value 的类型是什么?我的猜测是后者的类型为any @VLAZ 那么newMaterialFormGroup 的类型是FormGroup,我在函数参数中明确设置了它。这就是我好奇的原因;我最初传递了 newMaterialFormGroup 的值,但 TS 没有实现它,并且没有抛出关于将 value 转换为 FormGroup 的错误。我刚刚检查了一下,value 的类型是 any,所以这实际上是有道理的……我仍然在思考这一切,哈哈。 好吧,any 可以分配给任何东西,所以......就是这样。它基本上是来自类型检查系统的转义子句。只要有可能,您应该使用unknown 而不是any。它在某种程度上是相似的,因为可以说let x: unknown = 4 - 任何东西都可以分配给unknown。但是,unknown 不能分配给任何东西,let y: number = x; 会导致编译失败,除非您检查类型是否正确。这使得unknown 很有用,因为它用作“通配符”类型,但不会绕过类型系统。 很高兴知道这一点!请提供答案,我一定会接受。谢谢! 【参考方案1】:

问题似乎是newMaterialFormGroup.value 的类型是any。这就是为什么当它被传递到预期 FormGroup 的地方时没有编译错误 - any 可以分配给任何东西,所以......就是这样。它是来自类型检查系统的转义子句。

应尽可能使用unknown 而不是any。它在某种程度上是相似的,因为它充当通配符类型,任何东西都可以分配给unknown。然而,unknown 不能分配给任何东西:

let a: any = 4;    // OK
let b: number = a; // OK

let x: unknown = 4; // OK
let y: number = x;  // Error

Playground Link

您必须明确检查 unknown 值,然后才能分配它:

let x: unknown = 4; // OK

let y: number = -1;
if (typeof x === "number")
    y = x; // OK

Playground Link

这使得unknown 很有用,因为它仍然用作“通配符”类型,但不会绕过类型系统。

更多信息请见:'unknown' vs. 'any'

【讨论】:

以上是关于为啥 TypeScript 4 转译器没有看到这个不正确的类型传递给函数?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Typescript 在转译代码中将 .default() 添加到类构造函数中?

预处理器和转译器有啥区别?

您如何将伊斯坦布尔代码覆盖率与转译的 Typescript 一起使用?

TypeScript 转译的文件是不可执行的

在没有 TypeScript Transpiler 的情况下使用 Angular 2

将 Typescript 的 baseUrl 编译器选项与节点一起使用