Appearance
存取器属性
在 TypeScript 中,存取器(Getter/Setter)的语法与 JavaScript 几乎一致。通过存取器,我们可以截获对对象成员的访问和设置操作,从而实现更精细的控制(如数据验证、副作用处理等)。
基本用法
typescript
class Animal {
// 私有属性,外部无法直接访问
private _age: number;
// ES2022 私有字段
#type: string;
constructor(
public name: string,
protected color: string,
age: number,
type: string,
) {
this._age = age;
this.#type = type;
}
// Getter: 获取 age
get age() {
return this._age;
}
// Setter: 设置 age,包含验证逻辑
set age(value: number) {
if (value < 0 || value > 150) {
throw new Error('年龄不符合规范...');
}
this._age = value;
}
// Getter: 获取 type
get type(): string {
return this.#type;
}
// Setter: 设置 type,限制特定字符串
set type(value: 'Cat' | 'Dog') {
this.#type = value;
}
}
const a = new Animal('小白', '白色', 3, 'Dog');
// 访问 Getter
console.log(a.age); // 3
// 触发 Setter (验证失败)
// a.age = -1; // Error: 年龄不符合规范...
// 触发 Setter (成功)
a.type = 'Cat';提示
如果类中只定义了 get 而没有 set,则该属性会自动被推断为 readonly。
常见陷阱:可选属性与存取器
当我们将私有属性定义为可选属性(?)并配合存取器使用时,常常会遇到类型冲突的问题。
问题复现
typescript
class Animal {
// 可选属性:类型为 number | undefined
private _age?: number;
// Getter 推断返回类型为 number
get age() {
// Error: 不能将类型“number | undefined”分配给类型“number”。
return this._age;
}
set age(value: number) {
this._age = value;
}
}报错原因: 开启 strictNullChecks(严格空值检查)后,_age 可能是 undefined,而 Getter 声明(或推断)的返回类型通常是确定的 number,二者不兼容。
解决方案
方案一:移除可选标记(推荐)
如果属性本来就不应该是空的,直接移除 ?,确保在构造函数中初始化。
typescript
class Animal {
private _age: number = 0; // 给定初始值
}方案二:移除 Setter
如果只需要读取,不需要修改,可以移除 Setter。这样 Getter 的返回值类型会自动推断包含 undefined。
方案三:在 Getter 中处理 undefined
确保 Getter 始终返回确定的类型。
typescript
get age(): number {
if (this._age === undefined) {
throw new Error('年龄未知');
}
return this._age;
}方案四:非空断言(慎用)
如果你确定访问时 _age 一定有值,可以使用 ! 断言。
typescript
get age(): number {
return this._age!;
}方案五:调整 TS 配置(不推荐)
在 tsconfig.json 中设置 "strictNullChecks": false。这会关闭整个项目的严格空值检查,可能会引入更多隐患,通常不建议这样做。
json
{
"compilerOptions": {
"strictNullChecks": false
}
}