在一个项目上陷入了一个奇怪的境地.以下是TS显示错误的示例:

type Fruit = {
  name: string;
};

const myFruits: Fruit[] = [{ name: "Apple" }, { name: "Banana" }];

let asyncFuncResult: string | undefined = "NewName";
const asyncFuncResultConst: string | undefined = "NewName";
let result;

// Why TS shows an issue here?
if (asyncFuncResult) {
  result = myFruits.map(
    (fruit): Fruit => {
      return {
        ...fruit,
        name: asyncFuncResult
      };
    }
  );
}

它对第name: asyncFuncResult行说:

Type 'string | undefined' is not assignable to type 'string'.
Type 'undefined' is not assignable to type 'string'

Screenshot of issue example

以下是我找到的解决方法的演示和方法: CodeSandBox Demo

但我不明白为什么它会显示错误.如果变量是未定义的,我们不会进入条件块.因此,我们不可能将未定义的值赋给字符串.

推荐答案

TypeScrip只是对控制流分析持悲观态度(参见#9998).

The type of asyncFuncResult is string in the same scope where you checked the variable (inside the if).
But when you use it in the callback of the map operator it is used in another scope - and since it is a variable (i.e. let) it could be changed by some other code before the callback is executed, so typescript pessimistically assumes string | undefined

if (asyncFuncResult) {
  const aString = asyncFuncResult; // type of asyncFuncResult = 'string'
  result = myFruits.map(
    (fruit): Fruit => {
      return {
        ...fruit,
        name: asyncFuncResult // type of asyncFuncResult = 'string' | undefined
      };
    }
  );
}

我建议改用常量:

let asyncFuncResult: string | undefined = "NewName";
const asyncFuncResultConst = asyncFuncResult;

if (asyncFuncResultConst) {
  const aString = asyncFuncResultConst;
  result = myFruits.map(
    (fruit): Fruit => {
      return {
        ...fruit,
        name: asyncFuncResultConst
      };
    }
  );
}

非空断言操作符(!)也可以工作,但我会尽量避免它.

Typescript相关问答推荐

Angular -使用Phone Directive将值粘贴到控件以格式化值时验证器不工作

如何获取数组所有可能的索引作为数字联合类型?

了解TS类型参数列表中的分配

用泛型类型覆盖父类函数导致类型y中的Property x不能赋给基类型Parent中的相同属性."'''''' "

如果存在ts—mock—imports,我们是否需要typescpt中的IoC容器

如何使函数接受类型脚本中具有正确类型的链接修饰符数组

编剧错误:正在等待Expect(Locator).toBeVisible()

是否有一个版本的联合类型递归地使属性只出现在一个可选选项中?

Angular:ngx-echart 5.2.2与Angular 9集成错误:NG 8002:无法绑定到选项,因为它不是div的已知属性'

如何在Vue中使用Enum作为传递属性的键类型?

TypeScrip:从对象中提取和处理特定类型的键

如何将父属性类型判断传播到子属性

(TypeScript)TypeError:无法读取未定义的属性(正在读取映射)"

如何在省略一个参数的情况下从函数类型中提取参数类型?

将超类型断言为类型脚本中的泛型参数

如何从抽象类的静态方法创建子类的实例?

替换typescript错误;X类型的表达式可以';t用于索引类型Y;带有未定义

Angular 16:无法覆盖;baseUrl;在tsconfig.app.json中

我可以使用对象属性的名称作为对象中的字符串值吗?

如何从 Select 元素中删除选项