Appearance
访问修饰符
TypeScript 中的类结构主要包含属性、构造函数、方法、存取器、访问修饰符、装饰器等。我们可以像声明变量和函数一样,为这些成员添加类型标注。
访问权限对比
TypeScript 提供了三种访问修饰符(public、protected、private)以及 ES2022 的私有字段(#),用于控制类成员的可访问性。
| 修饰符 | 含义 | 类内部 | 子类 | 实例对象 | 备注 |
|---|---|---|---|---|---|
public | 公开 | ✅ | ✅ | ✅ | 默认值。如果不加修饰符,默认为 public。 |
protected | 受保护 | ✅ | ✅ | ❌ | 只能在类及其子类中访问。 |
private | 私有 | ✅ | ❌ | ❌ | 仅限类内部访问。TS 编译后会消失。 |
# | 私有字段 | ✅ | ❌ | ❌ | ES2022 标准。运行时真正的私有,编译后保留。 |
代码演示
typescript
class Animal {
// ES2022 私有字段
#type: string;
constructor(
public name: string, // public: 随处可访问
protected color: string, // protected: 仅类和子类可访问
private _age: number, // private: 仅类内部可访问 (TS检查)
type: string,
) {
this.#type = type;
}
show() {
console.log(`Name: ${this.name}, Color: ${this.color}, Age: ${this._age}`);
// 类内部可以访问所有修饰符修饰的成员
}
}
class Cat extends Animal {
info() {
// ✅ public: 子类可访问
console.log(this.name);
// ✅ protected: 子类可访问
console.log(this.color);
// ❌ private: 子类不可访问
// console.log(this._age); // Error: Property '_age' is private...
// ❌ #private: 子类不可访问
// console.log(this.#type); // Error: Property '#type' is not accessible...
}
}
const a = new Animal('小白', '白色', 3, 'Dog');
// ✅ public: 实例可访问
console.log(a.name);
a.show();
// ❌ protected: 实例不可访问
// console.log(a.color); // Error
// ❌ private: 实例不可访问
// console.log(a._age); // Error构造函数参数属性(简写)
TypeScript 提供了一种简写语法,可以在构造函数的参数前直接添加访问修饰符(public、private、protected),从而自动声明同名属性并完成赋值。
写法对比
typescript
// 普通写法
class Point {
public x: number;
public y: number;
constructor(x: number, y: number) {
this.x = x;
this.y = y;
}
}typescript
// 简写形式
class Point {
constructor(
public x: number,
public y: number,
) {}
}注意:目前
#私有字段不支持在构造函数中通过简写形式声明。
常见问题与注意事项
1. 属性初始化检查
在 strict: true 模式下,TypeScript 会默认开启 strictPropertyInitialization,要求类的非可选属性必须在构造函数中初始化。
解决方案
如果不想在构造函数中初始化,可以使用非空断言操作符 ! 或配置 tsconfig.json。
typescript
class User {
name!: string; // 告诉 TS 我稍后会初始化它
}或者关闭配置:
json
{
"compilerOptions": {
"strictPropertyInitialization": false
}
}2. private vs #
private:TypeScript 的语法糖。在编译成 JavaScript 后,private修饰符会被移除,运行时代码中该属性实际上是公开的(虽然 TS 编译器会报错,但在 JS 运行时可以通过(a as any)._age访问)。#:ES2022 的标准特性。编译后依然保留(或通过 WeakMap polyfill),在运行时提供真正的私有性,无法从外部访问。
