📦 Class Basics
TypeScript's class syntax is very similar to Java/C++, but compiles to JavaScript's prototype chain mechanism under the hood.
class Animal {
name: string;
sound: string;
constructor(name: string, sound: string) {
this.name = name;
this.sound = sound;
}
speak(): string {
return `${this.name} says ${this.sound}!`;
}
}
const cat = new Animal("小猫", "喵");
console.log(cat.speak()); // "小猫 says 喵!"
💡 Key difference from Java/C++:
TypeScript class properties must be declared in the class body or via parameter property shorthand in the constructor. Unlike Java, you can't use undeclared fields directly in the constructor.
🔒 Access Modifiers
TypeScript provides three access modifiers, consistent with Java/C++ concepts.
class BankAccount {
public owner: string; // 公开(默认)
protected balance: number; // 子类可访问
private pin: string; // 仅类内部可访问
readonly accountId: string; // 只读,初始化后不可修改
constructor(owner: string, balance: number, pin: string) {
this.owner = owner;
this.balance = balance;
this.pin = pin;
this.accountId = crypto.randomUUID();
}
public getBalance(): number { return this.balance; }
private validatePin(input: string): boolean { return input === this.pin; }
public withdraw(amount: number, pin: string): boolean {
if (!this.validatePin(pin) || amount > this.balance) return false;
this.balance -= amount;
return true;
}
}
ES native private fields (truly isolated at runtime):
class SecureVault {
#secret: string; // 真正的私有字段,运行时也无法从外部访问
constructor(secret: string) {
this.#secret = secret;
}
reveal(): string {
return this.#secret;
}
}
const vault = new SecureVault("密码");
// vault.#secret; // ❌ 语法错误:运行时和编译时都不允许
🔄 Comparison with Java:
TS's private is a compile-time check — at runtime you can still access it via (obj as any).pin. For runtime isolation, use the #field syntax (ES2022 private fields).
🔄 Comparison with Python:
Python uses _ (convention-private) and __ (name mangling) to indicate access levels. TS has explicit public/private/protected keywords with strict compile-time checks.
✨ Parameter Property Shorthand
This is TypeScript-specific syntactic sugar — adding an access modifier before a constructor parameter automatically declares and assigns a property of the same name.
// ❌ 传统写法需要:声明属性 → 构造函数参数 → 手动赋值(三步)
// ✅ 参数属性简写:一步到位
class User {
constructor(
public name: string,
private age: number,
readonly email: string,
) {}
getAge(): number {
return this.age;
}
}
💡 Practical advice:
Parameter property shorthand is extremely common in simple data classes. But if the constructor has complex logic (like parameter validation), mixing shorthand with manual assignment may reduce readability.
🧬 Inheritance
Use the extends keyword for class inheritance, consistent with Java's single inheritance model.
class Animal {
constructor(public name: string, protected sound: string) {}
speak(): string { return `${this.name}: ${this.sound}`; }
}
class Dog extends Animal {
constructor(name: string, public breed: string) {
super(name, "汪汪"); // 必须调用 super()
}
speak(): string {
return `🐕 ${super.speak()}!(品种:${this.breed})`;
}
fetch(item: string): string {
return `${this.name} 捡回了 ${item}`;
}
}
const dog = new Dog("旺财", "金毛");
console.log(dog.speak()); // "🐕 旺财: 汪汪!(品种:金毛)"
console.log(dog.fetch("飞盘")); // "旺财 捡回了 飞盘"
🎨 Abstract Classes
Abstract classes cannot be instantiated directly and are used to define template methods that subclasses must implement.
abstract class Shape {
abstract area(): number;
abstract perimeter(): number;
describe(): string {
return `面积: ${this.area().toFixed(2)}, 周长: ${this.perimeter().toFixed(2)}`;
}
}
class Circle extends Shape {
constructor(private radius: number) { super(); }
area(): number { return Math.PI * this.radius ** 2; }
perimeter(): number { return 2 * Math.PI * this.radius; }
}
class Rectangle extends Shape {
constructor(private width: number, private height: number) { super(); }
area(): number { return this.width * this.height; }
perimeter(): number { return 2 * (this.width + this.height); }
}
// const s = new Shape(); // ❌ 不能实例化抽象类
const circle = new Circle(5);
console.log(circle.describe()); // "面积: 78.54, 周长: 31.42"
🔌 Interface Implementation
Use implements to explicitly declare that a class follows an interface contract. A class can implement multiple interfaces.
interface Serializable {
serialize(): string;
}
interface Printable {
print(): void;
}
class Document implements Serializable, Printable {
constructor(public title: string, public content: string) {}
serialize(): string {
return JSON.stringify({ title: this.title, content: this.content });
}
print(): void {
console.log(`=== ${this.title} ===\n${this.content}`);
}
}
// 接口约束函数参数
function save(item: Serializable): void {
const data = item.serialize();
console.log("保存数据:", data);
}
const doc = new Document("笔记", "TypeScript 很棒");
save(doc);
💡 extends vs implements:
extends: Inherits a class and gets its implementation codeimplements: Declares adherence to an interface contract, must implement all methods yourself- Both can be used together:
class A extends B implements C, D
⚡ Static Members
Static properties and methods belong to the class itself, not instances. Commonly used for factory patterns and utility methods.
class IdGenerator {
private static nextId: number = 1;
static generate(): number {
return IdGenerator.nextId++;
}
static reset(): void {
IdGenerator.nextId = 1;
}
}
console.log(IdGenerator.generate()); // 1
console.log(IdGenerator.generate()); // 2
// 单例模式
class Config {
private static instance: Config | null = null;
private constructor(public readonly env: string) {}
static getInstance(): Config {
if (!Config.instance) {
Config.instance = new Config(process.env.NODE_ENV ?? "development");
}
return Config.instance;
}
}
🎭 Introduction to Decorators
Decorators are a special syntax used to enhance class and method behavior without modifying the original code. Widely used in frameworks like NestJS and Angular.
// 方法装饰器:自动记录方法调用日志
function log(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const original = descriptor.value;
descriptor.value = function (...args: any[]) {
console.log(`调用 ${propertyKey}(${args.join(", ")})`);
const result = original.apply(this, args);
console.log(`${propertyKey} 返回: ${result}`);
return result;
};
}
class UserService {
@log
findById(id: number): string {
return `User_${id}`;
}
}
const service = new UserService();
service.findById(42);
// 输出:
// 调用 findById(42)
// findById 返回: User_42
⚠️ Notes:
TypeScript 5.0+ supports the TC39 Stage 3 decorator standard. Legacy experimental decorators require "experimentalDecorators": true in tsconfig.json. NestJS and Angular currently still use the legacy syntax.
📝 Chapter Summary
Class Basics
Property declarations, constructors, methods — syntax similar to Java/C++, compiles to JS prototype chain
Access Modifiers
public/private/protected/readonly; #field provides runtime isolation
Parameter Property Shorthand
Constructor parameters with modifiers auto-declare + assign — TypeScript-exclusive syntactic sugar
Inheritance and Abstract Classes
extends single inheritance; abstract defines template methods that subclasses must implement
Interface Implementation
implements declares contracts, supports multiple interface implementation
Static Members and Decorators
Static members for factory/singleton patterns; decorators enhance class behavior, widely used in frameworks