如何解决`unknown` 和 `void` 之间的区别
根据this answer:
改用 void
意味着 forEach 承诺不使用返回值,因此可以使用返回任何值的回调调用它
根据TypeScript 3.0 release notes
... unkNown
是 any
的类型安全对应物。任何东西都可以分配给 unkNown
,但 unkNown
不能分配给任何东西,除了它本身和 any
...
尽管我这么想,但从这些描述中我找不到这些类型之间的任何区别。
我还注意到,与 unkNown
不同,当 void
用作函数参数的类型时,调用函数时可以省略该参数,即使它没有标记为可选:
declare const x: (a: void) => void
x()
虽然这种行为在处理通用代码时有时很有用,但看起来很奇怪。如果 void
应该只用于返回类型,为什么它有这种特殊的行为,不像其他类型?
解决方法
经过与Aluan Haddad的长时间讨论,我的理解如下:
unknown
是所有其他类型的超类型。在其他语言中,这主要是 void
类型 - 任何东西都可以分配给它,但它可以无用。
void
是一种特殊类型。一般情况下,它只是undefined的超类型,没有其他类型,甚至不是null
。
这使我们能够执行以下任何操作:
const x: void = undefined;
(): void => undefined;
(): void => {};
但阻止我们做任何事情:
const x: void = null;
const y: void = 5;
(): void => 5;
不过,与其他类型不同。 void
如果用于输出位置(作为返回类型的一部分)有一个特殊的行为:() => T
是任何 () => void
的 T
的子类型,其中包括 {{ 1}}、undefined
,当然还有 null
。
这可以执行以下操作:
void
const x: () => void = () => 5
存在和被使用的原因似乎更具有历史意义而不是实际,因为它在 void
之前就已经存在,并且它与类型系统的交互方式不同于所有其他类型(也会导致一些奇怪的事情,比如 unknown
不是 Promise<number>
的子类型)。
在这些类型之间做出决定的常用方法似乎是:
- 它是我只调用副作用的函数的返回类型吗?使用
Promise<void>
。 - 它是一种我打算以某种方式使用但不能保证的类型(返回与否)?使用
void
。
简短的版本是使用返回 void 的函数,调用者必须忽略它。
它是不同的 $ time ./random_perf
./random_perf 0.03s user 0.00s system 98% cpu 0.027 total
./random_perf
--------------------------------------------------------------------------------
Ir
--------------------------------------------------------------------------------
147,608,621 PROGRAM TOTALS
--------------------------------------------------------------------------------
Ir file:function
--------------------------------------------------------------------------------
106,311,924 /usr/lib/llvm-10/bin/../include/c++/v1/random:double std::__1::normal_distribution<double>::operator()<std::__1::mersenne_twister_engine<unsigned long,64ul,312ul,156ul,31ul,13043109905998158313ul,29ul,6148914691236517205ul,17ul,8202884508482404352ul,37ul,18444473444759240704ul,43ul,6364136223846793005ul> >(std::__1::mersenne_twister_engine<unsigned long,6364136223846793005ul>&,std::__1::normal_distribution<double>::param_type const&) [/home/xxx/EffectiveCpp/bin/random_perf]
22,905,902 /build/glibc-eX1tMB/glibc-2.31/math/../sysdeps/ieee754/dbl-64/e_log.c:__ieee754_log_fma [/usr/lib/x86_64-linux-gnu/libm-2.31.so]
6,000,007 /usr/lib/llvm-10/bin/../include/c++/v1/vector:main
3,003,122 /usr/lib/llvm-10/bin/../include/c++/v1/random:main
3,016 /home/xxx/EffectiveCpp/src/random_perf.cpp:main [/home/xxx/EffectiveCpp/bin/random_perf]
2,500,000 /build/glibc-eX1tMB/glibc-2.31/math/./w_log_template.c:log@@GLIBC_2.29 [/usr/lib/x86_64-linux-gnu/libm-2.31.so]
1,002 /usr/lib/llvm-10/bin/../include/c++/v1/memory:main
1,000 ???:0x000000000494b2f0 [???]
507,749 /build/glibc-eX1tMB/glibc-2.31/elf/dl-lookup.c:_dl_lookup_symbol_x [/usr/lib/x86_64-linux-gnu/ld-2.31.so]
因为 unknown
并没有明确表示“不要使用这个”,它只是表示它可以是任何东西。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。