共计 2402 个字符,预计需要花费 7 分钟才能阅读完成。
作者:Dr. Axel Rauschmayer
翻译:疯狂的技术宅
原文:https://2ality.com/2020/06/an…
未经允许严禁转载
在 TypeScript 中,any
和 unknown
是包含所有值的类型。在本文中,我们将会研究它们是怎样工作的。
TypeScript 的两种顶级类型
any
and unknown
are so-called top types in TypeScript. Quoting Wikipedia:
any
和 unknown
在 TypeScript 中是所谓的“顶部类型”。以下文字引用自 Wikipedia:
top type […]是 通用(universal) 类型,有时也称为 通用超类型 ,因为在任何给定类型系统中,所有其他类型都是子类型[…]。通常,类型是包含了其相关类型系统中所有可能的[值] 的类型。
也就是说,当把类型看作是值的集合时,any
和 unknown
是包含所有值的集合。顺便说一句,TypeScript 还有 bottom type never
,它是空集。
顶级类型 any
如果一个值的类型为 any
,那么我们就可以用它任何事:
function func(value: any) {
// 仅允许数字,但它们是 `any` 的子类型
5 * value;
// 通常,`value` 的类型签名必须包含 .propName
value.propName;
// 通常只允许带有索引签名的数组和类型
value[123];
}
任何类型的值都可以赋值给 any
类型:
let storageLocation: any;
storageLocation = null;
storageLocation = true;
storageLocation = {};
类型 any
也可被可赋值给每一种类型:
function func(value: any) {
const a: null = value;
const b: boolean = value;
const c: object = value;
}
使用 any
,我们将会失去通常由 TypeScript 的静态类型系统所给予的所有保护。因此,如果我们无法使用更具体的类型或 unknown
,则只能将其用作最后的手段。
示例:JSON.parse()
JSON.parse()
的结果取决于动态输入,这就是其返回类型为 any 的原因(我从函数签名中省略了参数 reviver
):
JSON.parse(text: string): any;
在 unknown
类型出现之前,JSON.parse()
就已经被添加到了 TypeScript 中。否则它的返回类型可能会是 unknown
。
示例:String()
把任意值转换为字符串的函数 String()
具有以下类型签名:
interface StringConstructor {(value?: any): string; // call signature
// ···
}
顶级类型 unknown
unknown
类型是 any
的类型安全版本。每当你想使用 any
时,应该先试着用 unknown
。
在 any
允许我们做任何事的地方,unknown
的限制则大得多。
在对 unknown
类型的值执行任何操作之前,必须先通过以下方法限定其类型:
- 类型断言
function func(value: unknown) {
// @ts-ignore: Object is of type 'unknown'.
value.toFixed(2);
// Type assertion:
(value as number).toFixed(2); // OK
}
- 相等:
function func(value: unknown) {
// @ts-ignore: Object is of type 'unknown'.
value * 5;
if (value === 123) { // equality
// %inferred-type: 123
value;
value * 5; // OK
}
}
- 类型防护:
function func(value: unknown) {
// @ts-ignore: Object is of type 'unknown'.
value.length;
if (typeof value === 'string') { // type guard
// %inferred-type: string
value;
value.length; // OK
}
}
- 断言函数:
function func(value: unknown) {
// @ts-ignore: Object is of type 'unknown'.
value.test('abc');
assertionFunction(value);
// %inferred-type: RegExp
value;
value.test('abc'); // OK
}
function assertionFunction(arg: unknown): asserts arg is RegExp {if (! (arg instanceof RegExp)) {throw new TypeError('Not a RegExp:' + arg);
}
}
本文首发微信公众号:前端先锋
欢迎扫描二维码关注公众号,每天都给你推送新鲜的前端技术文章
欢迎继续阅读本专栏其它高赞文章:
- 深入理解 Shadow DOM v1
- 一步步教你用 WebVR 实现虚拟现实游戏
- 13 个帮你提高开发效率的现代 CSS 框架
- 快速上手 BootstrapVue
- JavaScript 引擎是如何工作的?从调用栈到 Promise 你需要知道的一切
- WebSocket 实战:在 Node 和 React 之间进行实时通信
- 关于 Git 的 20 个面试题
- 深入解析 Node.js 的 console.log
- Node.js 究竟是什么?
- 30 分钟用 Node.js 构建一个 API 服务器
- Javascript 的对象拷贝
- 程序员 30 岁前月薪达不到 30K,该何去何从
- 14 个最好的 JavaScript 数据可视化库
- 8 个给前端的顶级 VS Code 扩展插件
- Node.js 多线程完全指南
- 把 HTML 转成 PDF 的 4 个方案及实现
- 更多文章 …