Inversify中@inject注入类型自动推断及类型错误校验方案问询
解决方案
实现这个需求的核心是预先把服务标识符和对应实现类的类型做全局映射,让TypeScript在编译阶段就能完成类型校验,不需要额外手动标注参数类型,常用的有两种落地方式:
方案1:自定义带类型的@inject装饰器
步骤1:定义全局服务类型映射
首先把所有服务标识符对应的实现类类型统一声明在一个接口里:
// 全局服务类型映射表,新增服务时只要在这里加对应条目即可 interface ServiceMap { B: typeof B // 其他服务示例: UserService: typeof UserService }
步骤2:声明带类型的TYPES常量
约束TYPES的key必须和ServiceMap的key一一对应:
const TYPES: Record<keyof ServiceMap, symbol> = { B: Symbol.for('B') }
步骤3:封装带类型推断的注入装饰器
对原生inversify的@inject做一层轻量封装,自动关联标识符对应的类型:
import { inject as rawInject } from 'inversify' export function inject<T extends keyof ServiceMap>(id: T) { return rawInject(id) as ( target: any, propertyKey: string | symbol | undefined, parameterIndex: number ) => void & { __paramType: InstanceType<ServiceMap[T]> } }
实际使用效果
注入时不需要手动标注参数类型,TypeScript会自动推断,类型不匹配直接编译报错:
@injectable() class A { // 不需要写 private b: B,TS自动识别b的类型是B constructor(@inject(TYPES.B) private b) {} test() { // 这里调用B的实例方法可以获得完整的类型提示,写错会直接报错 this.b.someMethodOfB() } }
方案2:给Container增加绑定阶段的类型校验
如果还需要提前捕获绑定阶段的类型不匹配错误(比如把TYPES.B绑定到A类的错误),可以对原生Container做扩展:
import { Container as RawContainer } from 'inversify' class TypedContainer extends RawContainer { bind<T extends keyof ServiceMap>(id: T) { const rawBinding = super.bind<InstanceType<ServiceMap[T]>>(id) return { ...rawBinding, to: (ctor: ServiceMap[T]) => rawBinding.to(ctor) } } } // 初始化容器 const container = new TypedContainer() // 正确写法,编译正常 container.bind(TYPES.B).to(B).inSingletonScope() // 错误写法,TS直接报错:类型typeof A不能赋值给类型typeof B container.bind(TYPES.B).to(A).inSingletonScope()
两种方案都没有运行时开销,所有校验都在TS编译阶段完成,能完全避免类型匹配混乱的问题。
内容的提问来源于stack exchange,提问作者Ilmarinen123
相关产品推荐
相关产品推荐

