"未知"和"虚空"之间的区别



根据这个答案:

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

根据 TypeScript 3.0 发行说明

unknownany的类型安全对应物。任何东西都可以分配给unknown,但unknown除了它自己和any之外,不能分配给任何东西......

尽管我想到了这个问题,但从这些描述中,我找不到这些类型之间的任何区别。

我还注意到,与unknown不同,当void用作函数参数的一种类型时,调用函数时可以省略该参数,即使它没有标记为可选:

declare const x: (a: void) => void
x()

操场

虽然这种行为在使用泛型代码时有时很有用,但它看起来很奇怪。如果void应该只在返回类型中使用,为什么它与其他所有类型不同,具有这种特殊行为?

经过与Aluan Haddad的长时间讨论,我的理解如下:

unknown是所有其他类型的超类型。 在其他语言中,这主要是void类型是什么 - 任何东西都可以分配给它,但它可以无所事事。

void是一种特殊类型。 在正常情况下,它只是未定义的超类型,没有其他类型,甚至没有null

这使我们能够执行以下任何操作:

const x: void = undefined;
(): void => undefined;
(): void => {};

但阻止我们做以下任何一件事:

const x: void = null;
const y: void = 5;
(): void => 5;

不过,与其他类型不同。 如果在输出位置使用(作为返回类型的一部分),void具有特殊行为:() => T是任何T() => void子类型,包括undefinednull,当然还有void

这样就可以执行以下操作:

const x: () => void = () => 5

void存在和使用的原因似乎更多的是历史而不是实际的,因为它在unknown之前就已经存在了,并且它与类型系统的交互方式与所有其他类型不同(这也导致了一些奇怪的事情,比如Promise<number>不是Promise<void>的子类型)。

在这些类型之间做出决定的常用方法似乎是:

  • 它是我只调用副作用的函数的返回类型吗?使用void.
  • 它是我打算以某种方式使用但无法保证的类型(返回与否)吗?使用unknown.

简短的版本是,使用返回 void 的函数,调用方必须忽略它。

这与unknown不同,因为unknown并没有明确表示"不要使用这个",它只是意味着它可以是任何东西。

最新更新