MST

星途 面试题库

面试题:TypeScript装饰器在实际项目中的应用

假设你正在开发一个基于Node.js的Web应用,需要对部分API接口进行权限验证和日志记录,描述如何使用TypeScript装饰器来优雅地实现这两个功能,并解释装饰器的执行顺序和原理。
42.6万 热度难度
前端开发TypeScript

知识考点

AI 面试

面试题答案

一键面试

1. 使用TypeScript装饰器实现权限验证和日志记录

  1. 安装依赖:确保项目中安装了typescriptreflect - metadata,因为装饰器需要reflect - metadata支持。
npm install typescript reflect - metadata --save - dev
  1. 配置tsconfig.json:在tsconfig.json中启用装饰器相关配置:
{
    "compilerOptions": {
        "experimentalDecorators": true,
        "emitDecoratorMetadata": true,
        "target": "ES6",
        "module": "commonjs",
        "outDir": "./dist",
        "rootDir": "./src"
    }
}
  1. 实现装饰器
    • 权限验证装饰器
import { ReflectMetadata } from'reflect - metadata';

const PERMISSION_KEY = 'permission';

// 权限验证装饰器
export function requirePermission(permission: string) {
    return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
        Reflect.defineMetadata(PERMISSION_KEY, permission, target, propertyKey);
        const originalMethod = descriptor.value;
        descriptor.value = function (...args: any[]) {
            // 这里模拟权限验证逻辑,从请求上下文中获取用户权限
            const userPermissions = ['admin']; // 模拟用户权限列表
            if (!userPermissions.includes(permission)) {
                throw new Error('Permission denied');
            }
            return originalMethod.apply(this, args);
        };
        return descriptor;
    };
}
- **日志记录装饰器**:
// 日志记录装饰器
export function log() {
    return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
        const originalMethod = descriptor.value;
        descriptor.value = function (...args: any[]) {
            console.log(`Calling method ${propertyKey} with args:`, args);
            const result = originalMethod.apply(this, args);
            console.log(`Method ${propertyKey} returned:`, result);
            return result;
        };
        return descriptor;
    };
}
  1. 在API接口中使用装饰器
class ApiController {
    @log()
    @requirePermission('admin')
    public someApiMethod() {
        return 'This is a protected API response';
    }
}

const controller = new ApiController();
try {
    controller.someApiMethod();
} catch (error) {
    console.error(error.message);
}

2. 装饰器执行顺序和原理

  1. 执行顺序:装饰器从目标方法的最内层向外层执行。在上述例子中,先执行requirePermission装饰器,再执行log装饰器。这是因为装饰器的应用顺序是从里到外,而实际执行是从外到里。
  2. 原理
    • 定义:装饰器本质上是一个函数,它可以接收三个参数:target(目标对象,可能是类、方法或属性),propertyKey(属性名,如果是类装饰器则为undefined),descriptor(属性描述符,如果是类装饰器则为undefined)。
    • 作用:装饰器可以在不改变原有代码逻辑的基础上,为目标对象添加额外的功能。例如,权限验证装饰器可以在方法执行前检查权限,日志记录装饰器可以在方法执行前后记录日志。
    • 元数据:通过reflect - metadata库,装饰器可以定义和读取元数据。例如,requirePermission装饰器使用Reflect.defineMetadata定义了权限相关的元数据,在实际权限验证逻辑中可以读取这些元数据。