为什么 TypeScript 有 `void` 和 `undefined`? [英] Why does TypeScript have both `void` and `undefined`?

查看:22
本文介绍了为什么 TypeScript 有 `void` 和 `undefined`?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

In TypeScript, you can annotate a function as returning void:

function fn1(): void {
  // OK
}

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

你也可以注释一个函数返回undefined:

You can also annotate a function to return undefined:

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

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

所以看起来如果你调用一个返回 void 的函数,你总是会得到 undefined 的值.但是你不能写这个代码:

So it seems that if you call a function returning void, you'll always get back the value undefined. Yet you can't write this code:

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

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

Why isn't void just an alias for undefined? Does it need to exist at all?

推荐答案

void 在函数返回类型中具有特殊意义,不是 undefined 的别名.这种想法是非常错误的.为什么?

void has special meaning in function return types, and is not an alias for undefined. Thinking of it this way is very wrong. Why?

void 的目的是不会观察到函数的返回值.这与undefined非常不同.区分这一点很重要,这样您就可以正确地描述像 forEach 这样的函数.让我们考虑一个独立版本的 Array#forEach,在回调返回位置用 undefined 而不是 void 编写:

The intent of void is that a function's return value will not be observed. This is very different from will be undefined. It's important to have this distinction so that you can properly describe functions like forEach. Let's consider a freestanding version of Array#forEach, written with undefined instead of void in the callback return position:

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

如果您尝试使用此功能:

If you tried to use this function:

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

你会得到一个错误:

输入数字"不可分配给类型未定义"

Type "number" is not assignable to type "undefined"

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

This is a correct error - you said you wanted a function that returned the value undefined, but you actually provided a function that returned the value number because that's why Array#push returns!

使用 void 代替意味着 forEach 承诺不使用返回值,因此可以使用返回任何值的回调调用它

Using void instead means that forEach promises not to use the return value, so it can be called with a callback that returns any value

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 浮动是一件危险的事情,很容易打败类型检查.

Why not just use any ? If you're actually the one implementing forEach, you really don't want that - having an any floating is a dangerous thing that can defeat typechecking very easily.

由此得出的推论是,如果您有一些返回类型为 void 的函数表达式,您无法确定调用该函数的结果是 undefined.

The corollary to this is that if you have some function expression whose return type is void, you cannot say with any certainty that the result of invoking that function is undefined.

在返回类型明确列为 void 的函数 body 中,TypeScript 将阻止您意外"返回一个值,即使这不会造成类型系统违规.这有助于捕获重构中出现的错误:

In a function body whose return type is explicitly listed as void, TypeScript will stop you from "accidently" returning a value, even though this wouldn't create a type system violation. This is helpful for catching bugs that appear from a refactoring:

// 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;
  };
}

这篇关于为什么 TypeScript 有 `void` 和 `undefined`?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆