文章目录
只读数组
TypeScript 允许声明只读数组,方法是在数组类型前面加上 readonly 关键字。
只读数组,删除、修改、新增数组成员都会报错。
const arr: readonly number[] = [1, 2, 3];
console.log(arr[2]); // 3 --正确
arr[1] = 2; // 报错
arr.push(4); // 报错
delete arr[0]; // 报错
子类型 number[] 继承了父类型 readonly number[] 的所有特征,并加上了自己的特征,所以子类型 number[] 可以用于所有使用父类型 readonly number[] 的场合,反过来就不行。
下面示例中,子类型 number[] 可以赋值给父类型 readonly number[],但是反过来就会报错。
let a1: number[] = [0, 1];
let a2: readonly number[] = a1; // 正确
let a3: number[] = a2; // 报错
下面示例中,函数 getArr() 的参数 arr 是一个 number[] 类型的数组,传入 readonly number[] 类型的数组就会报错。
function getArr(arr: number[]) {
console.log(arr);
}
const arr: readonly number[] = [1, 2, 3];
getArr(arr) // 报错
只读元组
元组也可以是只读的,不允许修改。跟数组一样,只读元组是元组的父类型。所以,只读元组不能替代元组,而元组可以替代只读元组。
let a: [number, number] = [1, 2];
let b: readonly [number, number] = a; // 正确
let c: [number, number] = b; // 报错
函数只读参数
函数定义时,在参数类型前加上 readonly 关键字,表示这是只读参数,函数内部不能修改这个参数。
function arraySum(arr: readonly number[]) {
arr[0] = 0; // 报错
}
对象只读属性
对象属性名前面加上 readonly 关键字,表示这个属性是只读属性,不能修改。
只读属性只能在对象初始化期间赋值,此后就不能修改该属性。
// 初始化赋值
const person: {
readonly age: number
} = { age: 20 };
person.age = 18; // 报错
// 自定义类型
type Point = {
readonly x: number;
readonly y: number;
};
// 初始化赋值
const p: Point = { x: 0, y: 0 };
p.x = 100; // 报错
若属性值是一个对象,readonly 修饰符并不禁止修改该对象的属性,只是禁止完全替换该对象。
// 属性值是对象
type Home = {
readonly resident: {
name: string;
age: number
};
}
const h: Home = {
resident: {
name: 'Vicky',
age: 42
}
};
h.resident.age = 32; // 正确
h.resident = {
name: 'Kate',
age: 23
} // 报错
注意:下面事例中,可写对象 w 赋给只读对象 r ,由于引用类型的赋值,实际赋的是地址,所以修改可写对象的属性也会影响只读对象的属性。
// 可写对象
let w: {
name: string;
age: number;
} = {
name: '小七',
age: 20,
};
// 自读对象
let r: {
readonly name: string;
readonly age: number;
} = w;
w.age = 18;
console.log(r.age); // 18
类只读属性
属性名前面加上 readonly 修饰符,就表示该属性是只读的。实例对象不能修改这个属性。构造方法中修改和设置只读属性的值是可以的。
// 实例对象操作
class A {
readonly id = 'foo';
}
const a = new A();
a.id = 'bar'; // 报错
// 构造方法操作
class B {
readonly id: string = 'aaa';
constructor() {
this.id = 'bbb'; // 正确
}
}
const b = new B();
console.log(b.id); // 最终值为构造函数中设置的值
接口只读属性
接口属性名前面加上 readonly 关键字,表示这个属性是只读属性,不能修改。
// 定义接口
interface IPerson {
readonly name: string
}
// 赋初始值
let obj: IPerson = {
name: 'jack'
}
obj.name = 'rose'; // 报错