跳到主要内容

TypeScript - 只读属性

在 TypeScript 中,如果你希望某个属性在对象创建后就不能再被修改,可以使用 readonly 修饰符。只读属性可以在类外部访问,但不能修改。这在你希望保护对象的某些关键字段时非常有用,比如 ID、创建时间等。

使用 readonly 能帮助你防止意外修改,提高代码的健壮性。

语法

定义只读属性的语法如下:

readonly propName: type;
  • readonly 是关键字。
  • propName 是只读属性的名称。
  • type 是只读属性的类型。

声明只读属性

你可以在类中使用 readonly 关键字来声明只读属性。一旦赋值(通常是在构造函数中),这个属性就不能再被修改。

示例:

class Employee {
readonly empCode: number;
empName: string;

constructor(code: number, name: string) {
this.empCode = code;
this.empName = name;
}
}

let emp = new Employee(1001, "Jack");
console.log(emp.empCode); // 输出: 1001
emp.empName = "Tom"; // 正确:empName 是可变的
// emp.empCode = 1002; // 错误:无法修改只读属性

你可以看到,empCode 一旦在构造函数中赋值,就不能在类的外部(或内部的其他方法中)修改。

类属性的只读限制

你可能会好奇,readonly 是不是意味着“永远不能赋值”?其实不是。你可以在以下两个地方给只读属性赋值:

  1. 声明时赋初值;
  2. 构造函数中赋值。

示例:

class Student {
readonly rollNumber: number = 1; // 声明时赋值
readonly name: string;

constructor(name: string) {
this.name = name; // 构造函数中赋值
}
}

一旦超出这两个时机,你就不能再更改只读属性。

接口中的只读属性

readonly 也可以用于接口中,用于定义对象的不可变属性。

示例:

interface Person {
readonly id: number;
name: string;
}

let person: Person = {
id: 101,
name: "Alice"
};

person.name = "Bob"; // 正确
// person.id = 102; // 错误:无法修改只读属性

接口中的 readonly 同样表示你不能修改这个字段,哪怕它是一个普通对象。

类型别名中的只读属性

类型别名也可以包含只读属性,类似于接口。

示例:

type Point = {
readonly x: number;
readonly y: number;
};

let p1: Point = { x: 10, y: 20 };
// 错误:无法分配到 'x',因为它是只读属性。
// p1.x = 5;

console.log(p1.x, p1.y); // 输出: 10 20

const 的区别

readonlyconst 都有“不可变”的意味,但作用范围不同:

  • const 是用于 变量 的,意味着变量绑定不能更改。
  • readonly 是用于 属性(class 或 interface) 的,表示属性的值不能被修改。

举个例子:

const x = 10; // x 不能重新赋值

而:

class A {
readonly value = 42; // this.value 不能重新赋值
}

何时使用只读属性

  • 数据完整性:当你希望确保对象的某些属性在初始化后不会被更改时。
  • 函数式编程:在强调不可变性的编程范式中。
  • API 合约:当你创建的对象将暴露给外部用户,并需要保证内部状态不会被意外更改时。

小结

TypeScript 的只读属性为确保数据完整性和不可变性提供了强大的支持。通过 readonly 关键字,你可以控制对象属性的可修改性,从而提高代码的安全性和可维护性。在实际开发中,合理使用只读属性可以帮助你避免不必要的副作用,特别是在处理复杂对象和 API 设计时。掌握只读属性的使用,是成为 TypeScript 高级开发者的必经之路。