Angular TypeScript:“类型 '(string | undefined)[]' 不能分配给类型 'string[]'。”

Tho*_*hoe -1 typescript angular

我正在编写由 Adam Freeman撰写的Pro Angular 9一书。第 8 行抛出错误:

private categories: string[] = [];
Run Code Online (Sandbox Code Playgroud)

错误是

Error: src/app/model/product.repository.ts:13:7 - error TS2322:
Type '(string | undefined)[]' is not assignable to type 'string[]'.
  Type 'string | undefined' is not assignable to type 'string'.
    Type 'undefined' is not assignable to type 'string'.
Run Code Online (Sandbox Code Playgroud)

我不知道那条线是什么意思。变量如何既是字符串又是数组?

更让我困惑的是,Angular 说错误在第 13 行,而不是第 8 行。这是第 13 行:

Error: src/app/model/product.repository.ts:13:7 - error TS2322:
Type '(string | undefined)[]' is not assignable to type 'string[]'.
  Type 'string | undefined' is not assignable to type 'string'.
    Type 'undefined' is not assignable to type 'string'.
Run Code Online (Sandbox Code Playgroud)

除了在带有过滤器的数组上运行映射之外,我不知道该行的作用。

该文件还有两个错误。第 17 行:

this.categories = data.map(p => p.category).filter((c, index, array) => array.indexOf(c) == index).sort();
Run Code Online (Sandbox Code Playgroud)
Type 'null' is not assignable to type 'string'.

Run Code Online (Sandbox Code Playgroud)

在 JavaScript 中,我会创建一个空字符串:var myString = ''. 在 TypeScript 中,为什么要将字符串设为 null?不是stringnull不同的类型吗?

第三个错误在第 22 行:

getProducts(category: string = null): Product[] {
Run Code Online (Sandbox Code Playgroud)
Type 'Product | undefined' is not assignable to type 'Product'.
  Type 'undefined' is not assignable to type 'Product'.
Run Code Online (Sandbox Code Playgroud)

我不知道这意味着什么。

这是整个文件:

Type 'null' is not assignable to type 'string'.

Run Code Online (Sandbox Code Playgroud)

这是product.model.ts

return this.products.find(p => p.id == id);
Run Code Online (Sandbox Code Playgroud)

这引发了另一个错误:

Unexpected token. A constructor, method, accessor, or property was expected.

第 22 行的错误是由于Product类中的错误造成的吗?Product课堂上有什么错误?看起来这个类有一个构造函数。

我去书的GitHub repo下载了最新的文件,和书上的一样。

小智 7

我不明白告诉明显正在学习的人“关闭严格模式”的价值,因为如果你今天正在学习 Angular 和 Typescript,那么严格的类型检查是一个现实,也是一件非常好的事情。它可以更好地优化构建。此外,还有一些 linting 规则可以防止使用空断言运算符,以帮助您编写可以优化的更好的代码。这本书适用于使用旧版 Typescript 的 Angular 9,并且它们都没有将严格的类型检查强制执行到今天的水平。

这段代码不会因为启用了严格模式而抛出错误——它会抛出错误,因为输入的内容不再正确。这段代码在 Angular 9 中没问题,但在较新的版本中会引发错误。在将旧项目升级到 Angular 10 和 11 时,我也遇到了这些问题,我没有关闭严格模式 - 我修复了代码以使其更好。

这个错误:

Type 'Product | undefined' is not assignable to type 'Product'.
  Type 'undefined' is not assignable to type 'Product'.
Run Code Online (Sandbox Code Playgroud)

不是因为打开了严格模式,而是因为 JavaScript Array 方法undefined在未定义索引时返回。所以这一行

return this.products.find(p => p.id == id);
Run Code Online (Sandbox Code Playgroud)

可以返回 aProduct或者undefined如果具有该 ID 的产品不存在。你需要理解并处理它。

这个错误

Type 'null' is not assignable to type 'string'.
Run Code Online (Sandbox Code Playgroud)

是因为null是 TypeScript 中的一个类型。您需要正确键入此内容。

getProducts(category: string = null): Product[] {
Run Code Online (Sandbox Code Playgroud)

应该改为

getProducts(category: string | null = null): Product[] {
Run Code Online (Sandbox Code Playgroud)

如果这听起来像咆哮,我很抱歉,因为它不是。当我回答有关 stackoverflow 的问题时,我会尝试通过教学来更好地理解潜在问题。


Lin*_*ink 5

这里发生了很多事情,我将尝试逐步解释:

首先,看起来你已经'strict'在 Angular 中打开了模式。现在,因为您正在关注一本书,所以我建议您将其关闭,因为它基本上可以实现严格的打字和其他类似的功能。一般来说,在实际项目中这是一个很好的做法,因此您可以避免任何可能的错误,但在这里您可以安全地禁用它。要禁用它,请将tsconfig.json键设置strictfalse

错误:src/app/model/product.repository.ts:13:7 - 错误 TS2322:类型“(string | undefined)[]”不可分配给类型“string[]”。输入“字符串|” undefined' 不可分配给类型'string'。类型“未定义”不可分配给类型“字符串”。

一旦关闭严格模式,上述问题就不再是问题了。TS 编译器在这里基本上说的是,您要分配[]string[]ie 数组应包含字符串值,但在这种情况下,您只是将其初始化为空数组,因此会引发错误。这就是严格模式的工作原理。如果您想打开严格模式但又解决了这个问题,您可以使用 Non-null 断言运算符!来告诉 TS 编译器该值[]不为 null 或未定义。就像下面这样:

private categories: string[] = []!;
Run Code Online (Sandbox Code Playgroud)

一旦禁用严格模式,下面的代码也将停止抛出错误。它基本上是源于上述初始化和严格模式本身的连锁错误。

下面解释一下代码的工作原理: 该代码使用 ES6+ Arrow 语法。发生的情况是,您正在使用该Array.prototype.map()函数来迭代从data该方法检索的数组,并将每个对象的属性从该数组getProducts()映射到一个新数组,然后在该新数组上,您基本上使用该函数并根据每个元素的索引是其索引的条件过滤元素,然后对其调用函数。然后将整个结果存储到类实例的属性中。categorydataArray.prototype.filter()Array.prototype.sort()categories

this.products = data;
this.categories = data.map(p => p.category).filter((c, index, array) => array.indexOf(c) == index).sort();
Run Code Online (Sandbox Code Playgroud)

最后,由于启用了“严格”​​模式,以下代码也会引发错误:

return this.products.find(p => p.id == id);
Run Code Online (Sandbox Code Playgroud)

并且,回答以下问题:

在 JavaScript 中,我会创建一个空字符串:var myString = ''。在 TypeScript 中为什么要将字符串设置为空?string 和 null 不是不同的类型吗?

string 是原始类型,因此您可以为其分配 null。老实说,无论是 JS 还是 TS。您无法分配 null 的原因又是由于严格模式。如果您打开了严格模式并且仍然想分配 null 或未定义的值作为初始化,您可以使用非 null 断言运算符,!如下所示:

const myString: string = null!;
Run Code Online (Sandbox Code Playgroud)