类、继承与修饰器
本节目标
- 用
class写类型 + 实现,理解implements与extends - 掌握
public / private / protected / readonly - 初识「修饰器(Decorator)」做什么
TS 的 class 同时是「类型」和「运行时代码」。
// 运行环境:Node.js 16+ + typescript(需开启 experimentalDecorators 或 TS 5.0+);
// 运行:npx tsc ts-l13.ts && node ts-l13.js
// 用 interface 约束「类必须实现哪些方法」
interface Logger {
log(msg: string): void
}
class FileLogger implements Logger {
private filePath: string // private:仅类内部可见
constructor(path: string) {
this.filePath = path
}
log(msg: string): void {
console.log(`[${this.filePath}] ${msg}`)
}
}
// 继承:复用 + 扩展
class TimestampLogger extends FileLogger {
log(msg: string): void {
super.log(`[${new Date().toISOString()}] ${msg}`)
}
}
const logger = new TimestampLogger('app.log')
logger.log('启动') // [app.log] [2026-...] 启动修饰器(TS 5 稳定特性)是「贴在类/方法上的注解」,编译期/运行期增强行为:
// 一个「方法耗时统计」修饰器
function measure(target: any, key: string, desc: PropertyDescriptor) {
const fn = desc.value
desc.value = function (...args: any[]) {
const t = Date.now()
const r = fn.apply(this, args)
console.log(`${key} 耗时 ${Date.now() - t}ms`)
return r
}
}
class Calc {
@measure
heavy(): number { return 1 + 1 }
}
new Calc().heavy() // 打印耗时名词解释
类(class):TS 里 class 同时身兼两职:既是「运行时创建对象的蓝图」(new 出实例),又是「类型」(能当注解用)。implements 表示「这个类承诺实现某个接口的所有成员」;extends 表示「继承另一个类,复用它的能力」。
修饰器(Decorator):一种「贴在类/属性/方法上的标签」,用来在不改动原代码的前提下给它加功能(日志、缓存、校验等)。它本质是「编译期/运行期的包裹函数」。NestJS、Angular 大量用它,是 TS 工程化的标志性特性。
课后练习
练习 1:写 Animal 基类(有 name 和 eat()),Dog 继承它并新增 bark()。
答案:
class Animal { constructor(public name: string) {} eat(): void { console.log(`${this.name} 吃`) } } class Dog extends Animal { bark(): void { console.log('汪') } }
练习 2:private 和「不写修饰符(默认 public)」有什么区别?
答案:默认
public,类外也能访问;private仅在类内部可访问,类外访问会编译报错,是 TS 编译期的访问限制(运行时仍是普通属性)。protected则允许子类访问、禁止外部。
总结
我的观点:TS 的 class 让「面向对象」在前端有了类型保障,但请记住前端其实没那么需要继承。很多初学者一上来就 extends 一大串,结果耦合得改不动。我的经验法则是:能用组合(把小对象拼起来)就别用继承;只有「确实是『是一种(is-a)』关系且要复用行为」才继承。修饰器则是「横切关注点」(日志、权限、缓存)的利器,能显著减少重复包裹代码,但别为了炫技而加——每个修饰器都要解决一个真实重复问题。最后提醒:private 只是编译期约定,不是运行时加密,别拿它当安全边界。