MST
星途 面试题库

面试题:TypeScript装饰器的参数与元数据

假设你正在开发一个基于TypeScript的Web应用,需要在类的方法上使用装饰器来添加权限控制,装饰器接收一个字符串数组作为参数表示允许访问的角色。请实现这个装饰器,并说明如何使用反射来获取装饰器参数以及相关元数据。
19.5万 热度难度
前端开发TypeScript

知识考点

AI 面试

面试题答案

一键面试
  1. 实现装饰器
import 'reflect-metadata';

// 定义装饰器
function checkPermissions(allowedRoles: string[]) {
    return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
        const originalMethod = descriptor.value;
        descriptor.value = function (...args: any[]) {
            // 这里假设可以通过某种方式获取当前用户的角色,比如从上下文或者JWT中解析
            const currentUserRole = 'admin'; // 示例角色
            if (allowedRoles.includes(currentUserRole)) {
                return originalMethod.apply(this, args);
            } else {
                throw new Error('Permission denied');
            }
        };
        return descriptor;
    };
}
  1. 使用反射获取装饰器参数及元数据
class MyClass {
    @checkPermissions(['admin', 'editor'])
    myMethod() {
        console.log('This is my method');
    }
}

// 获取装饰器参数
const metadataKey = Symbol('allowedRoles');
Reflect.defineMetadata(metadataKey, ['admin', 'editor'], MyClass.prototype,'myMethod');
const allowedRoles = Reflect.getMetadata(metadataKey, MyClass.prototype,'myMethod');
console.log(allowedRoles);

// 调用方法
const myObj = new MyClass();
myObj.myMethod();
  1. 说明
    • 首先,引入reflect - metadata库,这是在TypeScript中使用反射功能的基础。
    • checkPermissions装饰器接收一个允许角色的字符串数组作为参数,并返回一个函数。这个返回的函数会在目标方法定义时被调用,它修改了目标方法的描述符,在原方法执行前检查当前用户角色是否在允许列表中。
    • 在类的定义中,使用@checkPermissions装饰器来装饰myMethod方法。
    • 通过Reflect.defineMetadata方法来定义元数据,将允许的角色数组与目标方法关联起来。然后使用Reflect.getMetadata方法来获取这些元数据。这样就可以在运行时获取到装饰器的参数。

注意,在实际应用中,获取当前用户角色的逻辑应该是从真实的认证和授权机制中获取,而不是像示例中简单硬编码。