Typescript异步函数返回类型void vs Promise <void>

时间:2020-01-09 13:06:49

标签: typescript

打字稿void和Promise 类型之间是否有区别?

问,因为我很困惑为什么这是一个有效的打字稿?

const asyncFunc: () => void = async () => {
    await new Promise(resolve => resolve());
};

这不是唯一有效的情况吗?

const asyncFunc: () => Promise<void> = async () => {
    await new Promise(resolve => resolve());
};

3 个答案:

答案 0 :(得分:7)

是的,有区别

void有点像any的相反:根本没有任何类型。您可能通常将其视为不返回值的函数的返回类型

我猜Promise<void>不需要解释。


现在为什么允许问题中的作业?因为可以在所有(几乎)与源函数相同的情况下调用目标函数(() => void)。看一个简化的例子:

declare let voidFunc: () => void;
declare let promiseFunc: () => Promise<void>;

voidFunc = promiseFunc; // OK
promiseFunc = voidFunc; // Error: Type 'void' is not assignable to type 'Promise<void>'

答案 1 :(得分:3)

当您声明类型为() => void的变量时,基本上是在说它可以是任何函数。因此,它的值(函数)可以返回任何值。看一下this playground。我向您提供了更多的函数实现,可以看到声明一个接收函数的变量与声明一个函数本身是不同的。 声明函数本身具有您期望的行为。

const asyncFunc: () => void = async () => {
    await new Promise(resolve => resolve());
};

const asyncFunc2: () => Promise<void> = async () => {
    await new Promise(resolve => resolve());
};

const asyncFunc3 = async () => {
    await new Promise(resolve => resolve());
};

// TS compiler complains about it
async function asyncFunc4(): void {
    await new Promise(resolve => resolve());
}

async function asyncFunc4(): Promise<void> {
    await new Promise(resolve => resolve());
}

编辑: 发现this的解释很少。它也可以帮助您理解它。它说:

对于返回值将被忽略的回调,请使用返回类型void。 原因:使用void更安全,因为它可以防止您以未经检查的方式意外使用x的返回值

答案 2 :(得分:2)

这也将正常工作(请注意,这甚至不是异步功能):

const asyncFunc: () => void = () => {
  return Math.random() > 0.5 ? 'hello' : 'world';
};

// OR this:
const asyncFunc2: () => void = () => {
  return { nice: 'very '};
};

为什么?基本上,您可以让打字稿解释类型本身,也可以将特定类型设置为常量。

在这里,您定义了一个名为asyncFunc的常量,其类型为() => void。这意味着在定义类型时,打字稿将忽略函数的返回值。可以将其视为用户不希望输入的值,因此返回值仍然可以正常工作,并且不会破坏代码。

那么asyncFunc是什么类型?

如果您自己定义常量的类型,则类型将为() => void,因此用户不会期望任何返回值: enter image description here

但是,如果让打字稿自己解释,它应该知道正确的值。 因此,对于上面定义的功能(没有异步),它将为() => stringenter image description here

那你该怎么办?

特别是对于将函数定义为() => void的情况,该函数根本不会检查返回值,并且您可以返回任何内容(甚至是promise)。 将函数定义为异步只会将返回值包装在一个承诺中,而() => void类型将忽略该承诺。

如果要定义与解释类型不同的返回值类型,则可以定义异步函数以嵌套类型返回特定的Promise。

您的示例如下:

const asyncFunc: () => Promise<void> = async () => {
    await new Promise(resolve => resolve());
};

问题是,这将在没有类型定义的情况下自动发生: enter image description here

所以这很多余。您可以只让打字稿解释类型,除非您想将返回类型更改为其他类型。

因此,在可能返回helloworld的示例中,我们可能想让用户知道返回值可以是任何字符串而不是这两个值。 然后,有必要将返回值的定义更改为其他内容: enter image description here

您可以组合使用其中任何一种来实现所需的工作流程,但是请注意,() => void在这种类型的系统中是一种特殊情况(因为除void以外的任何其他返回值都将引发输入错误。