You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用tsyringe时未传可选构造参数报错的原因及解决方法

使用tsyringe处理构造函数可选参数时的注入问题

问题场景

我正在使用tsyringe管理依赖注入,以下代码在传入sheepProps时可正常运行:

import 'reflect-metadata'
import {autoInjectable,singleton} from 'tsyringe'

interface sheepProps {
    legCount: number
}

@singleton()
export class Animal {
  makeSound (sound: string) {
    console.log(sound)
  }
}

@autoInjectable()
class Sheep {
  constructor(sheepProps?: sheepProps, private animal?:Animal) {}

  beeeeh () {
    this.animal.makeSound('bleeeeh')
  }
}

const props: sheepProps = {
    legCount: 4
} 

const sheep = new Sheep(props);
sheep.beeeeh();

但将构造调用改为new Sheep()(不传入sheepProps)时,抛出错误:

Error: Cannot inject the dependency "sheepProps" at position #0 of
"Sheep" constructor. Reason:
TypeInfo not known for "Object"

我的推测是:未传入sheepProps时tsyringe尝试对其注入,这个假设是否正确?如何修复以支持构造函数可选参数?


解答

你的推测完全正确

@autoInjectable()装饰器的逻辑是:当调用new Class()时,会自动为构造函数中未传入的参数尝试依赖注入。你的sheepProps是第一个参数,不传它时,tsyringe会尝试注入这个参数,但sheepProps是TypeScript接口(编译后不存在对应的JS类型,反射无法获取其类型信息),所以tsyringe不知道该注入什么,因此抛出错误。

修复方案

方案1:调整参数顺序(最简单)

将需要依赖注入的参数(比如Animal)放在构造函数参数的前面,不需要注入的可选配置参数放在最后。这样tsyringe会优先注入前面的依赖,后面的可选参数如果不传则不会被尝试注入:

@autoInjectable()
class Sheep {
  // 交换参数顺序,Animal在前,sheepProps在后
  constructor(private animal?: Animal, sheepProps?: sheepProps) {}

  beeeeh () {
    this.animal.makeSound('bleeeeh')
  }
}

此时不管是new Sheep(props)还是new Sheep()都能正常运行:

  • 传props时,Animal由tsyringe注入,sheepProps使用传入的值
  • 不传props时,Animal正常注入,sheepProps为undefined

方案2:使用@inject(undefined)标记无需注入的参数

如果需要保留原参数顺序,可以用@inject(undefined)显式告诉tsyringe某个参数不需要依赖注入,直接使用传入值(没传则为undefined):

import { autoInjectable, singleton, inject } from 'tsyringe'

// ...其他代码不变

@autoInjectable()
class Sheep {
  constructor(
    @inject(undefined) sheepProps?: sheepProps, 
    private animal?: Animal
  ) {}

  beeeeh () {
    this.animal.makeSound('bleeeeh')
  }
}

这种方式适合必须保留参数顺序的场景,明确标记哪些参数是手动传入的,哪些是由DI注入的。

方案3:为参数注册可注入的默认值(仅适用于类类型)

如果sheepProps不是接口而是一个类,可以提前在tsyringe容器中注册它的默认实例,这样不传参数时tsyringe会自动注入默认值:

import 'reflect-metadata'
import {autoInjectable,singleton, container} from 'tsyringe'

// 将sheepProps改为类
class SheepProps {
  legCount: number = 4;
}

// 注册默认实例
container.register(SheepProps, { useValue: new SheepProps() });

@singleton()
export class Animal {
  makeSound (sound: string) {
    console.log(sound)
  }
}

@autoInjectable()
class Sheep {
  constructor(sheepProps?: SheepProps, private animal?:Animal) {}

  beeeeh () {
    this.animal.makeSound('bleeeeh')
  }
}

// 不传参数时,sheepProps会使用注册的默认实例
const sheep = new Sheep();
sheep.beeeeh();

注意:此方法仅适用于类类型,因为TypeScript接口在编译后会被移除,无法被tsyringe反射识别。


内容的提问来源于stack exchange,提问作者SecretIndividual

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 05:07:39