TypeScript为什么同时具有`void`和`undefined`?

问题描述 投票:2回答:1

在TypeScript中,您可以将函数注释为返回void

function fn1(): void {
  // OK
}

function fn2(): void {
  // Error
  return 3;
}

您还可以注释一个函数以返回undefined

function fn3(): undefined {
  // OK
  return;
}

function fn4(): undefined {
  // Error
  return 3;
}

因此,如果您调用返回void的函数,则总是会获得undefined值。但是您不能编写以下代码:

function fn5(): void {
}
let u: undefined = fn5(); // Error

为什么void不只是undefined的别名?它根本不需要存在吗?

typescript undefined void
1个回答
4
投票

void在函数返回类型中具有特殊含义,并且不是undefined的别名。这样想是非常错误。为什么?

void的意图是函数的返回值将不会被观察。这与将为undefined完全不同。重要的是要有这种区别,以便您可以正确描述forEach之类的功能。让我们考虑一下Array#forEach的独立版本,在回调返回位置用undefined而不是void编写:

declare function forEach<T>(arr: T[], callback: (el: T) => undefined): void;

如果您尝试使用此功能:

let target: number[] = [];
forEach([1, 2, 3], el => target.push(el));

您会收到一个错误:

类型“数字”不可分配给类型“未定义”

这是正确的错误-您说您想要一个返回值undefined的函数,但实际上您提供了一个返回值number的函数,因为这就是Array#push返回的原因!

使用void表示forEach承诺不使用返回值,因此可以通过返回任何值的回调来调用它

declare function forEach<T>(arr: T[], callback: (el: T) => void): void;
let target: number[] = [];
// OK
forEach([1, 2, 3], el => target.push(el));

为什么不只使用any?如果您实际上是实现forEach的人,那么您真的不希望这样-浮动any是一件很危险的事情,很容易导致类型检查失败。

推论是,如果您有某个函数表达式的返回类型为void,则您不能确定地说调用该函数的结果是undefined

再次,voidnot undefined的别名,并且类型void的表达式可能具有any值,而不仅仅是undefined

在函数body中,其返回类型显式列出为void,即使不会造成类型系统冲突,TypeScript也会阻止您“意外”返回值。这有助于捕获重构中出现的错误:

// Old version
function fn(arr: number[]): void {
  const arr1 = arr.map(x => {
    return 3;
  });
}

// New version
function fn(arr: number[]): void {
  for (const x of arr) {
    // Oops, meant to do something else
    return 3;
  };
}
© www.soinside.com 2019 - 2024. All rights reserved.