Readonly<T>
最后更新:2026-10-22
Readonly<T> Readonly
Readonly<T> 把 T 的所有属性变为只读:对象创建之后不允许再给属性赋值,编译器直接报错。适合配置对象、快照、共享常量这类"造出来就不该被改"的数据。注意它锁的是属性,和 const 锁的变量绑定是两回事。
| 分组 | 工具类型 |
|---|---|
| 类型 | 类型 |
| 严格模式 | 不需要 |
ℹ️ 说明 编辑器将 TypeScript 转译为 JavaScript 后运行(不做类型检查);类型检查结果见示例 Output。
📝 语法
type Readonly<T> = {
readonly [K in keyof T]: T[K];
};
// 用法
const config: Readonly<AppConfig> = { appName: "docs", port: 8080, debug: false };
// config.debug = true; // 报错:无法分配到 debug,因为它是只读属性
⚙️ 参数
| T | 被变换的对象类型;映射类型遍历其每个属性并加上 readonly 修饰符 |
|---|
返回值:一个新类型:属性集合与 T 相同,但全部带 readonly 标记。
▶ 示例
修改下面的代码,点击试一试查看转译运行结果:
输出:
docs-site:8080
(转译后运行输出;只读保护由 tsc 静态保证——放开注释那行会得到 error TS2540,运行时 JS 本身并不阻止赋值)
💡 要点
ℹ️ 说明 实现是映射类型:[K in keyof T] 加 readonly 前缀。转译后 readonly 完全消失,没有 Object.freeze 那样的运行时保护。
⚠️ 注意 Readonly 是浅层的:嵌套对象属性整体变只读,但嵌套对象内部的字段仍可修改;数组属性变成 ReadonlyArray,但数组元素如果是对象照样可改。深只读要自写 DeepReadonly。
💡 提示 与 as const 的区别:Readonly<T> 作用于已有类型(不改变字面量推断,mode 还是 string 类型值);as const 作用于字面量本身(mode 收窄成 "dark")。需要字面量收窄用 as const,只需要"防改"用 Readonly。
🏷️ 相关工具类型
💡 相关案例
更多案例即将上线。
📚 相关教程
❓ 常见问题
Q Readonly 和 Object.freeze 有什么区别?
A Readonly 是纯编译期保护,转译后消失,运行时可改;Object.freeze 是运行时冻结,静默(或严格模式报错)阻止赋值。两者可以同时用:类型上 Readonly、运行时 freeze。
Q readonly 属性能通过 as 断言改掉吗?
A 可以绕过:(config as { debug: boolean }).debug = true 编译能过。这正说明 readonly 是编译期约定,不是运行时枷锁——绕过它等于主动放弃保护,团队代码里应禁止。
Q ReadonlyArray 和 readonly T[] 是什么关系?
A 完全等价:readonly T[] 是 ReadonlyArray<T> 的简写形式。两者都禁止 push/pop/修改下标,与 Readonly<T> 作用于对象属性同理,都是浅层只读。