Skip to content

快速开始

你通过流式 API 构建依赖图,TypeScript 会随着你的编写实时校验:每个依赖元组都会与目标构造函数的参数位置进行匹配,因此交换或缺失的参数是编译错误,而不是运行时的意外。这里没有 @Injectable() 装饰器,也没有 reflect-metadata —— 接线就是编译器能读懂的普通代码。

ts
import { Container } from '@inferdi/inferdi'

class Logger {
  log(message: string) {
    console.log(`[LOG] ${message}`)
  }
}

class UserRepo {
  constructor(
    private readonly logger: Logger,
    private readonly dsn: string,
  ) {}

  find(id: string) {
    this.logger.log(`Finding ${id} in ${this.dsn}`)
  }
}

const container = new Container()
  .registerValue('dsn', 'postgres://localhost/app')
  .registerClass('logger', Logger, [])
  .registerClass('userRepo', UserRepo, ['logger', 'dsn'])

container.get('userRepo').find('42')

registerClass('userRepo', UserRepo, ['logger', 'dsn']) 的调用会按位置进行校验。如果你把元组换成 ['dsn', 'logger'],TypeScript 会在应用运行之前报告这个不匹配。

解析值

使用 .get(key) 进行解析:

ts
const repo = container.get('userRepo')

该键必须在容器类型中注册过。未知的静态键是编译错误。动态键应在 .get(key) 之前用 .has(key) 探测。

选择生命周期

注册默认为 singleton。对于类,将生命周期作为第四个参数传入;对于工厂,则作为第三个参数。

ts
const root = new Container()
  .registerClass('logger', Logger, [])
  .registerClass('request', RequestContext, [], 'scoped')
  .registerClass('token', Token, [], 'transient')
类型创建时机是否缓存是否由容器释放
singleton每个拥有它的容器创建一次
scoped每个作用域创建一次
transient每次解析都创建

单例不能直接依赖 scopedtransient 服务。该规则由类型强制,并在严格模式下由运行时守卫强制。