根据这个答案:
改用
void
意味着 forEach 承诺不使用返回值,因此可以使用返回任何值的回调来调用它
根据 TypeScript 3.0 发行说明
。
unknown
是any
的类型安全对应物。任何东西都可以分配给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
子类型,包括undefined
、null
,当然还有void
。
这样就可以执行以下操作:
const x: () => void = () => 5
void
存在和使用的原因似乎更多的是历史而不是实际的,因为它在unknown
之前就已经存在了,并且它与类型系统的交互方式与所有其他类型不同(这也导致了一些奇怪的事情,比如Promise<number>
不是Promise<void>
的子类型)。
在这些类型之间做出决定的常用方法似乎是:
- 它是我只调用副作用的函数的返回类型吗?使用
void
. - 它是我打算以某种方式使用但无法保证的类型(返回与否)吗?使用
unknown
.
简短的版本是,使用返回 void 的函数,调用方必须忽略它。
这与unknown
不同,因为unknown
并没有明确表示"不要使用这个",它只是意味着它可以是任何东西。