As Const:一个被低估的 TypeScript 特性
创始人
2025-07-06 02:31:41
0

你有没有感觉 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'

相关内容

热门资讯

如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
施耐德电气数据中心整体解决方案... 近日,全球能效管理专家施耐德电气正式启动大型体验活动“能效中国行——2012卡车巡展”,作为该活动的...
20个非常棒的扁平设计免费资源 Apple设备的平面图标PSD免费平板UI 平板UI套件24平图标Freen平板UI套件PSD径向平...
德国电信门户网站可实时显示全球... 德国电信周三推出一个门户网站,直观地实时提供其安装在全球各地的传感器网络检测到的网络攻击状况。该网站...
为啥国人偏爱 Mybatis,... 关于 SQL 和 ORM 的争论,永远都不会终止,我也一直在思考这个问题。昨天又跟群里的小伙伴进行...
《非诚勿扰》红人闫凤娇被曝厕所... 【51CTO.com 综合消息360安全专家提醒说,“闫凤娇”、“非诚勿扰”已经被黑客盯上成为了“木...
2012年第四季度互联网状况报... [[71653]]  北京时间4月25日消息,据国外媒体报道,全球知名的云平台公司Akamai Te...