23

As per the documentation, I inject a service in a controller's constructor, but it turns out as undefined.

processScraped.controller.ts

import { Controller, Post, Body } from '@nestjs/common'; import { ProcessScrapedService } from "./processScraped.service" console.log(`\nController - ProcessScrapedService = `, ProcessScrapedService) // logs : class ProcessScrapedService { ...... @Controller('processScraped') export class ProcessScrapedController { constructor(private readonly pss: ProcessScrapedService) { console.log(`constructor - pss = `, pss) // logs : undefined (Should not !) console.log(`constructor - this.pss = `, this.pss) // logs : undefined (Should not !) } @Post() async processScraped(@Body() body) { console.log(`processScraped - this.pss = `,this.pss) // logs : undefined (Should not !) return this.pss.processScraped(body) // TypeError: Cannot read property 'processScraped' of undefined } } 

So :

  • The service exists

  • It's imported and logged correctly as a service after import

  • When I inject it in my controller, it's undefined.

Maybe the problem is in the service definition?

processScraped.service.ts

import { Component } from '@nestjs/common'; @Component() export class ProcessScrapedService { async processScraped(body) { // Some logic here return } } 

... Or maybe in the module?

processScraped.module.ts

import { Module } from '@nestjs/common'; import { ProcessScrapedController } from './processScraped.controller'; import { ProcessScrapedService } from './processScraped.service'; console.log(`\Module - nProcessScrapedService = `, ProcessScrapedService) // logs : class ProcessScrapedService { ...... @Module({ controllers: [ProcessScrapedController], components: [ProcessScrapedService], }) export class ProcessScrapedModule { } 

I really can't see what I'm doing wrong here??

EDIT - here are my dependencies :

"dependencies": { "@nestjs/common": "^4.5.9", "@nestjs/core": "^4.5.10", "@nestjs/microservices": "^4.5.8", "@nestjs/mongoose": "^3.0.1", "@nestjs/testing": "^4.5.5", "@nestjs/websockets": "^4.5.8", "@types/mongoose": "^5.0.9", "bluebird": "^3.5.1", "dotenv": "^5.0.1", "elasticsearch": "^14.2.2", "express": "^4.16.3", "mongoose": "^5.0.16", "mongoose-elasticsearch-xp": "^5.4.1", "reflect-metadata": "^0.1.12", "rxjs": "^5.5.6", "shortid": "^2.2.8" }, "devDependencies": { "@types/node": "^8.0.0" } 

and my tsconfig.json :

{ "compilerOptions": { "target": "ES2017", "module": "commonjs", "lib": [ "dom", "es2017" ], "outDir": "../../dist/server", "removeComments": true, "strict": true, "noImplicitAny": false, "typeRoots": [ "node_modules/@types" ], "types": [ "node" ], "experimentalDecorators": true } } 
2
  • What version are you using? Could you share your tsconfig file? Commented May 1, 2018 at 8:03
  • @KamilMyśliwiec Alright, I have updated my question with my dependencies and tsconfig Commented May 1, 2018 at 18:06

5 Answers 5

59

The "emitDecoratorMetadata": true is missing in your tsconfig.json file.

Sign up to request clarification or add additional context in comments.

4 Comments

Oh wow O_o I have no idea what this is, but it fixed the problem. I would never have found that by myself. Thanks Kamil, you're the man.
had the same (similar) issue today, had to add the following to my tsconfig.json "experimentalDecorators": true, "declaration": true, "removeComments": true, "emitDecoratorMetadata": true
You saved my day, weird it's not included in the default nest new project template
Because of an issue with Jest test coverage in Angular, I did a global remove of emitDecoratorMetadata since Angular no longer needs it. Which also removed from nest which does still need the flag.
59

Just stumbled across the same issue in one of my providers - the problem was that I forgot to annotate the provider with an @Injectable() decorator after I have added it to the respective module.

2 Comments

Haha, I love when this happens. It's like a checklist with possible adjacent problems. Thanks!
Thank you so much for this. You just saved me from spinning my wheels for hours.
12

One of my providers was scoped with REQUEST scope. I removed it and it resolved more errors than one.

2 Comments

This should be upvoted higher
Also had an issue using @Inject(REQUEST) on a provider constructor elsewhere in my code.
8

Recently faced the same issue in a service that depends on a service in another module. While everything in the answers above is already in place, annotating the imported service with Inject(ImportedService) at the constructor solved the problem.

Comments

1

Sometimes, you'll need to scope your request, but doing so might result in crashing tests. Make sure you override the scope in your tests, using the Reflect trick:

 Reflect.defineMetadata( 'scope:options', { scope: Scope.DEFAULT }, YourService, ); 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.