** reflect-metadata 的作用、用法,并配合多个实用例子**,尤其是它如何结合 TypeScript 装饰器来实现高级功能,比如依赖注入、类型推断、字段注解等。


🧠 一、reflect-metadata 是什么?

reflect-metadata 是一个支持 元编程(Meta Programming) 的库,它允许你给类、属性、方法、函数参数添加“元信息”并在运行时读取这些信息。
大白话:类似于中间件,什么路由中间件啥的,写好后加在那个方法上就能去操作那个方法的或者类啥的能力,比如写个日志打印,添加到的函数都会被打印日志,比如路由中间件本身也是有种元编程能力,加上就能在加上的路由上都执行中间件,或者Refet,可以操作所有对象的属性方法啥的,proxy,被proxy代理的变量都会被监控getset等等,总之就是可以搞其他写好的程序的程序就喊具有元编程能力的程序

🎯 二、应用场景

应用

描述

🧱 类型系统扩展

读取类、方法、参数的类型

📦 依赖注入框架

自动注入构造函数参数的实例

📊 表单/数据校验

读取字段类型与校验规则

🧩 ORM 映射

标注类字段 → 数据库字段

🌐 路由控制器

使用装饰器定义路由、方法等


✅ 三、启用 reflect-metadata 前提

  1. 安装:
npm install reflect-metadata
  1. 在入口文件(如 main.ts)顶部引入:
import 'reflect-metadata'
  1. tsconfig.json 配置:
{"experimentalDecorators": true,"emitDecoratorMetadata": true
}

🚀 四、核心 API 用法示例

✅ 1. 属性元数据(使用装饰器 + metadata)

import 'reflect-metadata'function Label(label: string) {return Reflect.metadata('label', label)
}class User {@Label('用户名')name: string
}// 获取 name 字段的自定义元信息
const label = Reflect.getMetadata('label', User.prototype, 'name')
console.log(label) // 输出:用户名

✅ 2. 读取属性的类型信息(需要 emitDecoratorMetadata)

import 'reflect-metadata'class User {name: stringage: number
}const type1 = Reflect.getMetadata('design:type', User.prototype, 'name')
const type2 = Reflect.getMetadata('design:type', User.prototype, 'age')console.log(type1.name) // String
console.log(type2.name) // Number
  • 这是 TypeScript 编译器自动生成的类型信息。
  • design:type 是 reflect-metadata 保留的 key。

✅ 3. 读取方法参数类型(用于依赖注入)

import 'reflect-metadata'class LoggerService {}
class UserService {}class App {constructor(public logger: LoggerService, public userService: UserService) {}
}const paramTypes = Reflect.getMetadata('design:paramtypes', App)
console.log(paramTypes.map((t: any) => t.name)) // ['LoggerService', 'UserService']
  • 在依赖注入框架中,框架就能根据这些类型自动创建和注入实例。

✅ 4. 自定义字段验证装饰器

import 'reflect-metadata'function Required(target: any, key: string) {Reflect.defineMetadata('required', true, target, key)
}function isFieldRequired(target: any, key: string) {return Reflect.getMetadata('required', target, key)
}class Product {@Requiredname: stringprice: number
}console.log(isFieldRequired(Product.prototype, 'name')) // true
console.log(isFieldRequired(Product.prototype, 'price')) // undefined

🌍 五、结合场景示例:构建简易依赖注入容器

import 'reflect-metadata'class Logger {log(msg: string) {console.log('Log:', msg)}
}class Service {constructor(public logger: Logger) {}
}// 简易 DI 容器
function create<T>(target: new (...args: any[]) => T): T {const paramTypes = Reflect.getMetadata('design:paramtypes', target) || []const params = paramTypes.map((type: any) => new type())return new target(...params)
}const service = create(Service)
service.logger.log('Hello DI') // 输出:Log: Hello DI

🎯 利用 design:paramtypes 读取构造函数参数类型,并自动创建依赖项实例。


⚠️ 六、注意事项

限制

描述

类型信息只在 TS 编译时生成

必须开启 emitDecoratorMetadata

必须引入 reflect-metadata

否则 Reflect API 不可用

运行时类型是构造函数

例如 StringNumber,不是具体值类型


🧾 七、常用内置 Metadata Key

Key

描述

design:type

属性的类型

design:paramtypes

构造函数或方法的参数类型数组

design:returntype

方法的返回类型


✅ 总结


内容

📦 工具

reflect-metadata 提供在运行时定义/获取元信息的能力

🔧 搭配

常与装饰器、TypeScript 一起使用

💡 应用

依赖注入、类型反射、表单校验、ORM 等场景广泛使用

📌 核心 API

Reflect.defineMetadata()Reflect.getMetadata()design:type

🚀 必备配置

experimentalDecorators: true + emitDecoratorMetadata: true