这个构造函数与Angular依赖注入不兼容,因为其参数列表中索引为0的依赖项无效。

23
在我的 Angular 9 应用程序中,我有一个抽象类:
export abstract class MyAbstractComponent {
  constructor(
    protected readonly cd: ChangeDetectorRef,
  ) {
    super();
  }

  // ...
}

以及扩展它的组件:

@Component({
  // ...
})
export class MyConcreteComponent extends MyAbstractComponent {
  // ...
}

所有东西都正常工作,除了测试部分,我在那里遇到了以下错误:

错误:此构造函数与Angular依赖注入不兼容,因为参数列表中索引为0的依赖项无效。 如果依赖类型是原始类型(如字符串),或者该类的祖先缺少Angular装饰器,则可能会发生这种情况。

请检查1)索引为0的参数的类型是否正确,2)是否为此类及其祖先定义了正确的Angular装饰器。

13个回答

22
花了一些时间,但在使用 Angular 10.2.3 创建新应用程序后,我的 base tsconfig.json 中没有这个: "emitDecoratorMetadata": true, 在 compilerOptions 中! 将其再次添加到 tsconfig.json 后,DI 就能按预期工作了。

2
实际上,它只需要添加到tsconfig.spec.json中,因为它仅在测试文件中失败,至少在我的情况下是这样的... - BalB
你真是个天才。 - Bohao LI
在使用新的依赖项时,我立即修复了 Angular 14 上的错误。 - phil_lgr

17

在迁移到版本 9 时,我们遇到了相同的问题。最终我们发现忘记为一些抽象组件添加装饰器。从 v9 开始,使用 Angular DI 的所有类必须具有 Angular 类级别的装饰器。

来自Ivy兼容性示例的示例:

之前:

export class DataService {
  constructor(@Inject('CONFIG') public config: DataConfig) {}
}

@Injectable()
export class AppService extends DataService {...}

之后:

@Injectable() // <--- THIS
export class DataService {
  constructor(@Inject('CONFIG') public config: DataConfig) {}
}

@Injectable()
export class AppService extends DataService {...}

你好,我是Angular 9的新手。我遇到了这个问题,但是示例对我来说不太清楚。我该如何在我的组件中使用它? - hello world
在您的项目中查找任何扩展其他组件/服务/指令等的组件/服务/指令,并检查所有这些元素是否在其顶部具有Angular类级别装饰器(@Component@Injectable@Directive,...)。 - metodribic
有没有关于在抽象组件上添加装饰器与在每个扩展组件/服务中添加构造函数哪种方法更正确的资料?虽然两种解决方案都能工作,但对我来说似乎有些奇怪,尽管我不会感到惊讶。 - briosheje
我没有在任何地方找到关于在子类中调用super的文档,因此我更喜欢使用装饰器,因为这个解决方案是作为(高级)迁移指南的一部分记录下来的。 - metodribic
任何看到这篇回答的人可能会对 Angular 跟踪器上 此相关问题 上的讨论感兴趣。 - Coderer

7
在我的情况下,简单地重启npm解决了这个错误。

我也遇到了同样的问题,一开始非常疑惑为什么不起作用,后来停止了 npm 并重新运行了 ng serve 命令,问题就解决了。 - EM-Creations

7

我通过在MyConcreteComponent中添加构造函数并调用super(...)构造函数来解决了我的问题:

@Component({
  // ...
})
export class MyConcreteComponent extends MyAbstractComponent {

  // adding this block fixed my issue
  constructor(
    protected readonly cd: ChangeDetectorRef,
  ) {
    super(cd);
  }

  // ...
}

默认情况下提供一个模板:@Component({ template: '
' })
- Vifier Lockla

5

今天在使用Jest测试应用程序时,我不得不面对这个确切的错误。 我正在运行Angular 10.2,在另一个执行相同测试而没有抛出任何错误的规范文件中,每个类都有装饰器。 花了我一个小时才找到问题:我的测试文件中存在循环依赖,并且由于测试未显示常规的Angular警告,我没有注意到它。

因此,为了提醒其他遇到相同问题的人,请检查您的导入!


1
我遇到了同样的问题:将一些代码从主项目移动到我的库中。导入使用 @my-library 从库中导入,这在 ng serve 中可以工作,但在测试中失败了。当导入相同的库对象时,必须使用文件路径进行导入。 - ibenjelloun
1
谢谢你。我花了一些时间查找,很难找到导致循环依赖的缺失导入,但是你指引了我正确的方向。感谢! - Michael Norgren

4
在我的情况下,这是因为我在Git存储库 A 中,然后移动到另一个Git存储库(B),一些存在于存储库A中的服务在B中不存在。因此,通过简单地重新启动npm,这个错误消失了。希望对其他人有用。

我刚刚重新启动了应用程序:请再次运行“ng serve”。 - shutsman

2
当我不小心将一个import语句改为import type语句时,我收到了类似于这个错误消息(“Error: This constructor was not compatible with Dependency Injection.”)的内容:

错误的写法:

import type { AngularFirestore, AngularFirestoreDocument } from '@angular/fire/firestore'

@Injectable({
  providedIn: 'root'
})
export class CommentsApiService {

  constructor(
    private firestore: AngularFirestore
  ) { }

  // ...
}

正确

import { AngularFirestore } from '@angular/fire/firestore'
import type { AngularFirestoreDocument } from '@angular/fire/firestore'

@Injectable({
  providedIn: 'root'
})
export class CommentsApiService {

  constructor(
    private firestore: AngularFirestore
  ) { }

  // ...
}

1
在自己研究后,我来到这里给出答案。我发现了一个有趣的极端情况:通常,Angular语言服务(在VSCode中)会将使用import type来进行依赖注入标记为错误。 但是,如果您将非注入类转换为注入服务 而不 重新启动Angular语言服务,则似乎无法注意到您的构造函数现在正在使用DI。 - Coderer

2

补充一下这个问题的额外信息,我遇到了类似以下示例的错误。

import * as fromOtherLib from 'fromOtherLib';

@Component({
...
})
class ExampleComponent {
  constructor(private exampleService: fromOtherLib.ExampleService){}
}

所以我移除了* as fromOtherLib这部分,然后用解构导入代替,像这样:import { exampleService } from 'fromOtherLib';


我可以确认在 import * as Apollo from 'apollo-angular' 周围有类似的错误 - 切换到显式的 import { Apollo, Mutation, Query } from 'apollo-angular'; 也解决了我的问题。 - ciekawy

2
大痛苦啊。
我忘记在我的指令构造函数参数中加上@Inject(ElementRef)属性,结果就开始报错了。 错误的
constructor (private ElementRef : element)

正确

constructor (@Inject(ElementRef) private ElementRef : element)

0
在我的情况下,我有一个构造函数参数,但 DI 容器无法识别它。我将其标记为可选,这对于忽略它来说已经足够好了:
import { Optional } from '@angular/core';    

constructor(protected coolService: CoolService, @Optional() private name: string) {...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接