面试题答案
一键面试// 自定义Symbol用于存储类型元数据
const typeMetadataSymbol = Symbol('typeMetadata');
// 定义装饰器函数
function typeCheckDecorator(target, propertyKey, descriptor) {
const originalFunction = descriptor.value;
// 获取类型元数据
const typeMetadata = Reflect.getOwnMetadata(typeMetadataSymbol, target, propertyKey);
// 创建新的函数,进行类型检查
descriptor.value = function (...args) {
if (!typeMetadata) {
throw new Error('No type metadata defined for this function.');
}
if (args.length!== typeMetadata.length) {
throw new Error(`Expected ${typeMetadata.length} arguments, but got ${args.length}`);
}
for (let i = 0; i < args.length; i++) {
const arg = args[i];
const expectedType = typeMetadata[i];
if (typeof arg!== expectedType) {
throw new Error(`Argument at index ${i} should be of type ${expectedType}, but got ${typeof arg}`);
}
}
return originalFunction.apply(this, args);
};
return descriptor;
}
// 示例函数
class ExampleClass {
@typeCheckDecorator
addNumbers(a, b) {
return a + b;
}
}
// 设置类型元数据
Reflect.defineMetadata(typeMetadataSymbol, ['number', 'number'], ExampleClass.prototype, 'addNumbers');
// 测试
const example = new ExampleClass();
try {
console.log(example.addNumbers(1, 2));
console.log(example.addNumbers('1', 2)); // 这会抛出类型错误
} catch (error) {
console.error(error.message);
}
// 处理函数重载
class OverloadedClass {
@typeCheckDecorator
processInput(input) {
return `Processed string: ${input}`;
}
@typeCheckDecorator
processInput(input) {
return `Processed number: ${input}`;
}
}
// 设置不同重载的类型元数据
Reflect.defineMetadata(typeMetadataSymbol, ['string'], OverloadedClass.prototype, 'processInput', 0);
Reflect.defineMetadata(typeMetadataSymbol, ['number'], OverloadedClass.prototype, 'processInput', 1);
// 测试重载
const overloaded = new OverloadedClass();
try {
console.log(overloaded.processInput('test'));
console.log(overloaded.processInput(123));
} catch (error) {
console.error(error.message);
}
在上述代码中:
- 定义了一个
typeMetadataSymbol
用于存储函数的类型元数据。 typeCheckDecorator
装饰器函数获取函数的类型元数据,并在调用原函数前检查传入参数的类型。- 对于函数重载的情况,通过
Reflect.defineMetadata
的第四个参数(属性描述符索引)来区分不同的重载版本,并分别设置其类型元数据。