0Pricing
TypeScript Academy · 课时

readonly 属性

将对象属性标记为初始化后不可变。

readonly 属性 是 CoddyKit 上的免费 TypeScript Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 TypeScript Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 TypeScript Academy 课程共包含 4 节课。

只读修饰符

readonly 修饰符用于标记一个属性,表示该属性可以设置一次,但之后不能重新赋值。它在类型层面表达不可变性,有助于防止意外修改。

interface Point {
  readonly x: number;
  readonly y: number;
}
const p: Point = { x: 1, y: 2 };
console.log(p.x, p.y);
// p.x = 5; // Error: cannot assign to readonly property

接口中的只读属性

在接口中,readonly 用于说明哪些字段在创建后保持不变。使用者可以自由读取这些字段,但编译器会阻止任何重新赋值。

interface Config {
  readonly env: string;
  retries: number; // mutable
}
const c: Config = { env: 'prod', retries: 3 };
c.retries = 5; // allowed
console.log(c.env, c.retries);

重新赋值时的编译错误

尝试写入 readonly 属性会导致编译时错误。这可以发现一大类共享状态被意外修改的问题。

interface User {
  readonly id: number;
  name: string;
}
const u: User = { id: 1, name: 'Ada' };
u.name = 'Grace'; // ok
// u.id = 2; // Error
console.log(u);

类属性中的只读修饰符

类同样支持 readonly。只读字段可以在声明时或构造函数内部初始化,但不能在其他位置初始化。

class Circle {
  readonly radius: number;
  constructor(r: number) {
    this.radius = r; // allowed in constructor
  }
}
const c = new Circle(5);
console.log(c.radius);

在构造函数中设置一次

构造函数是在声明之外唯一可以为只读字段赋值的位置。构造完成后,该值在对象的整个生命周期内都会被锁定。

class Account {
  readonly owner: string;
  constructor(owner: string) {
    this.owner = owner;
  }
  rename() {
    // this.owner = 'x'; // Error: readonly outside constructor
  }
}
console.log(new Account('Sam').owner);

只读参数属性

TypeScript 的参数属性允许您直接在构造函数签名中声明并初始化只读字段,从而减少样板代码。

class Vector {
  constructor(
    readonly x: number,
    readonly y: number
  ) {}
}
const v = new Vector(3, 4);
console.log(v.x, v.y);

只读仅在编译时生效

需要特别注意的是,readonly 只存在于类型系统中。它会在运行时被擦除——JavaScript 没有这一概念。它只能阻止您在 TypeScript 代码中重新赋值,无法阻止通过无类型路径访问编译后输出的代码进行重新赋值。

interface Box { readonly value: number; }
const b: Box = { value: 10 };
// At runtime b is a plain object; readonly is not enforced by JS.
console.log(b.value);

只读与常量声明的区别

请不要混淆这两者。const 会阻止变量被重新绑定,而 readonly 会阻止属性被重新赋值。使用 const 声明的对象仍然可以拥有可变属性,除非这些属性被标记为 readonly。

const obj = { count: 0 }; // const binding
obj.count = 5; // allowed: property is mutable
console.log(obj.count);

本质上是浅层的

readonly 是浅层的:它保护的是属性本身,而不是该属性所指向的对象或数组的内容。即使对象引用是只读的,您仍然可以修改该对象的字段。

interface Holder { readonly data: { n: number }; }
const h: Holder = { data: { n: 1 } };
// h.data = {...}; // Error
h.data.n = 99; // allowed: inner field is not readonly
console.log(h.data.n);

使用只读创建更安全的接口

将返回对象的字段标记为 readonly,可以提醒调用方不要修改这些字段。它会在类型中明确表达意图,使误用成为编译错误,而不是悄无声息地造成错误。

interface Snapshot { readonly takenAt: number; readonly size: number; }
function snapshot(): Snapshot {
  return { takenAt: Date.now(), size: 1024 };
}
const s = snapshot();
console.log(s.size);

索引签名中的只读属性

您甚至可以将索引签名设为只读,从而生成一种类似映射的类型:其条目可以读取,但不能通过索引重新赋值。

interface Scores {
  readonly [name: string]: number;
}
const scores: Scores = { ada: 95, sam: 88 };
console.log(scores.ada);
// scores.ada = 100; // Error

快速检查

检验您对只读属性的理解。

回顾:只读属性

您已了解到 readonly:

  • 允许属性设置一次,之后阻止重新赋值。
  • 对于类字段,可以在声明时或构造函数中设置。
  • 仅在编译时生效,并且是浅层的——不会对嵌套数据进行深度冻结。
  • 它与 const 不同:前者保护属性,后者保护变量绑定。

接下来学习只读数组和元组。

interface Meta { readonly id: number; }
const m: Meta = { id: 42 };
console.log(m.id);

常见问题解答

「readonly 属性」课时是免费的吗?

是的 — 「readonly 属性」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 TypeScript Academy 课程的其余内容,请升级到 CoddyKit PRO。 TypeScript Academy 课程共包含 4 节课。

「readonly 属性」这节课中我会学到什么?

将对象属性标记为初始化后不可变。 你通过在浏览器中直接运行的动手代码来练习 TypeScript Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 TypeScript Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 TypeScript Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。

「readonly 属性」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 TypeScript Academy 课中编写并运行代码吗?

能。每节 TypeScript Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. readonly 属性
  2. readonly 数组与元组
  3. ReadonlyArray 与 ReadonlyMap
  4. 深度不可变模式
← 返回 TypeScript Academy