TypeScript:类型“string | undefined”不能赋值给类型“string”。

4
interface SomeType {
  a: string;
  b?: string;
}

const foo: SomeType = {
  a: 'hello',
  b: 'there'
};

const bar: SomeType = {
  a: 'hello'
};
bar.b = 'there';

// Error on this line
const str: string = foo.b;

// These lines have no error
const str2: string = foo.b ? foo.b : '';
const str3: string = foo.b!;
const str4: string = bar.b;

在上面的例子中,我们有两种方式创建一个具有可选属性bSomeType对象。声明foo时,我们在创建对象时设置了b的值。对于bar,我们是在对象创建后设置了一个b的值。
在创建第一个字符串str时,会出现错误: 类型“string | undefined”不能分配给类型“string”。类型“undefined”不能分配给类型“string”。ts(2322) 这个错误可以通过str2str3的方法来缓解。我理解在这些示例中,我们要么检查foo.b的值,要么断言我们知道foo.b有一个值。
我不明白为什么创建str4时没有出现错误。为什么TypeScript能够检测到bar.b不是undefined,但它无法检测到同样的结果foo.b呢?是我们设置属性的方式有什么问题导致出现这个错误吗?
(TypeScript版本3.8.2)

它看起来像是TypeScript可以知道bar.b要么是字符串,要么是未定义的。 - GrandFleet
因为 const 只适用于 foo 而不是 foo 的属性。所以 foo.b 不是 const,可能是 undefined。所有的解决方法都确保如果它是 undefined,则提供一个字符串(或者强制转换)。 - Dave Meehan
str2的简写是foo.b ?? ''。虽然这并不重要,但是foo.b === ''的结果是false,所以你将会重新赋值给另一个空字符串。 - eventHandler
2个回答

0

从行 const foo: SomeType = ... 中移除 SomeType 将使代码正常工作。

interface SomeType {
  a: string;
  b?: string;
}

const foo = {
  a: 'hello',
  b: 'there'
};

const bar: SomeType = {
  a: 'hello'
};
bar.b = 'there';

// No more error on this line
const str: string = foo.b;

// These lines have no error
const str2: string = foo.b ? foo.b : '';
const str3: string = foo.b!;
const str4: string = bar.b;

在原始代码中,您将对象{ a:..., b:...}转换为一个接口。在这种情况下,SomeType
const foo: SomeType = {
  a: 'hello',
  b: 'there'
};

最简单的例子是,如果您修改str4的最后一行以添加强制转换,您将产生相同的错误:

const str4: string = (bar as SomeType).b; // error, because of the cast

这样做可以消除错误,但我仍然不明白为什么编译器没有抱怨bar.b,它也是SomeType。如果我从创建foo的地方删除SomeType,TypeScript将不再强制要求foo与该接口匹配。如果接口描述了一个具有firstNamelastNameUser对象,则所有对象实现该接口非常重要。假设我更新以添加一个address属性到接口中。foo将不会收到编译器错误,但如果我将其用作User,我希望得到警告,以便我可以更新代码。 - supermeng
我认为编译器在类型声明时不会追踪嵌套值的赋值。但是我也没有建议您删除接口。正确使用该接口的方法是,所有操作b的代码都要检查undefined,因为您希望它适用于interface的所有实例。 - Nenad
换句话说,这是编译器的限制,但一般情况下使用 b 的方式也不是最佳实践。 - Nenad

-1

如果您在tsconfig.json文件中启用了angularCompilerOptions中的strictTemplates,则几乎所有组件中都有可能出现此错误。

enter image description here

从Angular 9开始,我们有了一个新功能叫做strictTemplates

  "angularCompilerOptions":{
    "strictTemplates": true
  }

这确实是一个很好的功能,但是如果你没有足够的时间来修复所有这些错误,你可以将其设置为false,例如当你有一个重要的发布时。

有一篇很好的博客文章更详细地解释了这个问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接