as const:一个被低估的 TypeScript 特性

更新日期: 2023-11-09 阅读: 1.3k 标签: Typescript

你有没有感觉 TypeScript中可能有一些被低估但却非常有用的工具,你并没有充分利用?的确有,今天我们要重点介绍一个:as const。它虽然沉默却强大,而且非常有力,是一个被低估的功能,但它的力量却强大无比。

理解 'as const'

以下是一个没有 as const 的代码片段:

const menu = {
home: '/home',
about: '/about',
contact: '/contact'
};

这个TypeScript的世界里,这个变量可以随心所欲地变化和改变。听起来很灵活,,但是这里有个陷阱。

请考虑这个 go to root 方法:

function goTo(route: 'home' | 'about' | 'contact') {
// some implementation
}

注意到了吗?如果你在 menu 对象中添加了另一条路由,你也需要更新函数 goTo 。这就是冗余,导致同一类型有多个真实来源。

as const 可以为我们解决这个问题。

TypeScript的期望与现实

当你在使用TypeScript时,有时你所期待的和实际发生的情况会痛苦地产生巨大的分歧。当我们试图从现有的类型中创建一个新的类型时,这种分歧变得非常明显。

这里有个例子。假设你有一个对象,你期望TypeScript只考虑这个对象的属性。但是,意外的是!TypeScript只把它当作一个字符串来考虑。

let route: keyof typeof menu;
route = 'store'; // No error

在这种情况下,TypeScript认为 route 是一个可能会发生变化的字符串。但是,我们希望基于属性的固定类型。我们的期望和现实并未对齐。

解决方案:'as const'

我们刚刚经历的那种痛苦的分歧,就是 as const 试图解决的问题。通过将易变属性改为不变属性, as const 使我们的期望与现实保持一致。

const menu = { 
home: '/home',
about: '/about',
contact: '/contact'
} as const;

通过这个简单的改变,我们的对象属性变成了只读。我们看看它如何影响我们之前的问题:

let route: keyof typeof menu; 
route = 'store'; // Error. Exactly what we wanted!

通过使用 as const 使对象变为不可变,TypeScript 现在明白 route 应该只允许提供的键。现在,我们得到了我们想要的确切结果:当我们试图设置无效值时,会出现类型错误。

与 object.freeze 的比较

你可能对JavaScript方法 Object.freeze() 有所了解。 Object.freeze() 和 as const 都可以使对象只读,但它们之间存在着关键的差异。

我们快速了解一下他们的能力:

const menuFrozen = Object.freeze({
home: '/home',
about: '/about',
contact: '/contact'
});

const menuConst = {
home: '/home',
about: '/about',
contact: '/contact'
} as const;

以及一些结果:

// 这不会改变任何东西,home 仍然是'/home'
menuFrozen.home = '/newHome';

// 编译时错误
menuConst.home = '/newHome';

通过 Object.freeze() ,我们拥有了一个运行时概念,可以防止JavaScript对象的更改。然而, Object.freeze() 并不影响 TypeScript 的类型推断。

另一方面,有了 as const ,TypeScript在编译时将对象视为不可变的,使你的类型检查更为严格,这有助于捕捉更多可能的错误。

因此,虽然 as const 和 Object.freeze() 在表面上看起来可能相似,但它们服务于不同的目的。 as const 在类型检查上更为强大,而 Object.freeze() 只在运行时强制实施不变性。

一个配合 'as const' 的更清洁的 'go to root' 函数

我们使用 as const 重构 goTo 函数:

function goTo(route: keyof typeof menu) {    
// some implementation
}

就这样,as const 使我们免于重复信息的愚蠢操作。我们可以从我们创建的对象中推断出一个类型。这样是不是更简洁了?

使用 'as const' 提取对象值

我们使用 as const 提取我对象值,颠覆TypeScript的规则,获取我们需要的所有详细信息,以编写强大且无bug的代码。这只需要一点类型魔法。

以下是一个示例:

type Routes = typeof menu[keyof typeof menu]; 
// Routes is now equal to '/home' | '/about' | '/contact'

来源: 大迁世界

本文内容仅供个人学习、研究或参考使用,不构成任何形式的决策建议、专业指导或法律依据。未经授权,禁止任何单位或个人以商业售卖、虚假宣传、侵权传播等非学习研究目的使用本文内容。如需分享或转载,请保留原文来源信息,不得篡改、删减内容或侵犯相关权益。感谢您的理解与支持!

链接: https://fly63.com/article/detial/12547

相关推荐

Nerv_一款类 React 前端框架,基于虚拟 DOM 技术的 JavaScript(TypeScript) 库

Nerv_是一款由京东凹凸实验室打造的类 React 前端框架,基于虚拟 DOM 技术的 JavaScript(TypeScript) 库。它基于React标准,提供了与 React 16 一致的使用方式与 API。

使用TypeScript两年后-值得吗?

差不多两年前,我在一个创业团队中开始了一个全新的项目。用到的全都是类似Microservices,docker,react,redux这些时髦的东西。我在前端技术方面积累了一些类似的经验

TypeScript最佳实践:是否使用noImplicitAny

我应该使用noImplicitAny TypeScript编译器标志吗?noImplicitAny编译器选项所做的,基本上是将TypeScript从可选类型语言转换为强制类型检验语言。这使得TypeScript离JavaScript的超集稍微远了一些,因为简单的:

为什么要学习Typescript 语言呢?Typescript 开发环境安装

TypeScript是一种由微软开发的自由和开源的编程语言。它是JavaScript的一个超集,TypeScript是JavaScript类型的超集,它可以编译成纯JavaScript。TypeScript可以在任何浏览器、任何计算机和任何操作系统上运行,并且是开源的。

5分钟了解TypeScript

有两种方式安装TypeScript,如何创建第一个TypeScript文件,在TypeScript中,可以使用interface来描述一个对象有firstName和lastName两个属性,TypeScript支持JavaScript的新功能,其中很重要的一个功能就是基于类的面向对象编程

Typescript中以变量方式传递类

最近尝试用TypeScript写一个工具库,需要实现这样一个场景:声明一个抽象类Parent,声明一组子类ChildA、ChildB继承这个Parent,实现它的抽象方法

TypeScript_TS系列之高级类型

交叉类型:将多个类型合并为一个类型、联合类型:表示取值可以为多种类型中的一种、混合类型:一个例子就是,一个对象可以同时做为函数和对象使用,并带有额外的属性、类型断言:可以用来手动指定一个值的类型

用TypeScript弥补Elm和JavaScript之间的差距

近些日子,我使用了新语言编程,从JavaScript,切确地说是Elm,转成TypeScript。在本文中,我将继续深挖一些我非常喜欢的TypeScript特性。

TypeScript_命名空间(namespace)

什么时候要用命名空间?如果你发现自己写的功能(函数/类/接口等...)越来越多, 你想对他们进行分组管理就可以用命名空间, 下面先用类,举例:发现namespace下还有export, export在这里用来表示哪些功能是可以外部访问的:

TypeScript功能:const断言

我发现官方的 TypeScript 文档非常有用,但是总觉得有点过于学术化并且枯燥无味。每当我发现一个新功能时,我想要知道这个功能究竟能够解决什么问题而不是长篇大论

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!