前言
在 TypeScript 日常开发中,as 和 const 是两个出现频率极高的关键字。它们有时独立出现,有时组合成 as const,让不少初学者感到困惑。
本文将用最直白的语言,结合代码示例,一次性讲清楚它们各自的用途与区别。
一、as 的三种核心用法
1. 类型断言(Type Assertion)
作用:手动指定一个值的类型,告诉 TypeScript 编译器:“相信我,我知道它是什么类型”。
核心特点:只发生在编译阶段,不影响运行时的实际数据。
语法:
值 as 类型
常见场景一:获取 DOM 元素
如果不加断言,getElementById 返回的是宽泛的 HTMLElement,无法直接使用 HTMLCanvasElement 特有的 getContext 方法。
typescript
// ❌ 报错:HTMLElement 上不存在 getContext
// const canvas = document.getElementById('myCanvas');
// canvas.getContext('2d');
// ✅ 断言为具体的 Canvas 元素类型
const canvas = document.getElementById('myCanvas') as HTMLCanvasElement;
canvas.getContext('2d'); // 正常运行
常见场景二:处理 any / unknown 类型
typescript
let data: unknown = 'hello world';
// 将 unknown 收窄为 string 才能调用字符串方法
(data as string).toUpperCase();
注意:还有一种尖括号写法
<类型>值,但在 React 的 TSX 文件中会与标签语法冲突,推荐统一使用as语法。
2. 常量断言(as const)
这是 as 最特殊的一种断言形式。它不仅仅是类型收窄,更是结构锁定。
作用:
- 将
string/number等基础类型推断为具体的字面量类型(如"GET"而不是string)。 - 为数组和对象的所有属性加上
readonly修饰符。
对比效果:
typescript
// 普通声明:类型较为宽泛
const colorsNormal = ['red', 'blue']; // 类型: string[]
const configNormal = { method: 'POST' }; // 类型: { method: string }
// 使用 as const:类型极度精确且只读
const colorsStrict = ['red', 'blue'] as const; // 类型: readonly ["red", "blue"]
const configStrict = { method: 'POST' } as const; // 类型: { readonly method: "POST" }
实际应用场景:定义路由配置、枚举常量池时非常有用。
typescript
// 假设后端要求 method 只能是这三个字符串之一
const apiConfig = {
url: '/user/login',
method: 'POST'
} as const;
// 这里 method 的类型是 "POST",而不是 string
// 保证了类型安全,不会写错成 'post' 或其他值
3. 模块导入别名
严格来说这属于 ES Module 语法,但在 TypeScript 文件中随处可见。
typescript
// 将整个模块重命名
import * as utils from './helpers';
// 将单个导出成员重命名(解决命名冲突)
import { useState as useReactState } from 'react';
二、const 的双重身份
1. JavaScript 层面的变量声明
这是运行时的约束,表示变量绑定不可重新赋值(注意:对象内部属性依然可变)。
javascript
const num = 10;
num = 20; // ❌ TypeError: Assignment to constant variable.
const obj = { a: 1 };
obj.a = 2; // ✅ 属性修改是允许的
obj = {}; // ❌ 引用本身不可修改
2. TypeScript 层面的常量断言
指的就是上文提到的 as const。
一句话区别总结:
| 用法 | 控制层面 | 核心目的 |
|---|---|---|
const 声明变量 | 运行时 | 防止变量被重新赋值 |
as const 断言 | 编译时类型系统 | 将类型锁定为最具体的字面量 |
三、实战演练:const 与 as const 的化学反应
我们来看一个经典的反直觉案例:
typescript
// 1. 使用 const 声明变量
const userRole = 'admin';
// 此时 TS 推断出的类型是 字面量类型 "admin"
// 因为 const 声明的变量永远不变,TS 会智能收窄为字面量
// 2. 但是看这里!
const roles = ['admin', 'user'];
// 此时 TS 推断出的类型是 string[] (宽泛的数组)
// 因为数组内容未来可能被 push 修改
如果你想让 roles 也拥有像单变量那样的字面量精确度,就必须请出 as const:
typescript
const roles = ['admin', 'user'] as const;
// 类型:readonly ["admin", "user"]
此时,roles 变成了只读元组,既保证了值运行时不可变,又保证了类型编译时精确。
四、总结
as 类型:编译时的“后门”,用于类型断言,小心使用。as const:编译时的“锁”,用于字面量固化,推荐在多常量配置中使用。const变量:运行时的“锁”,用于防止引用变化。
理解这三点,TypeScript 中 90% 的 as 和 const 相关报错你都能从容应对。
如果觉得本文有帮助,欢迎点赞收藏,有问题也可以在评论区交流~