In the documentation you mentioned:
It is incredibly easy to manage dependencies with TypeScript. If you are not TypeScript enthusiast and you work with plain JavaScript, you have to do it in this way:
This is slightly confusing since there's not mention of how to "manage dependencies with TypeScript" and the examples in the documentation will not run unless I add the @Dependencies([UsersService]) decorator. Without this decorator I'd get this exception:
[Nest] 2031 - 4/11/2017, 1:08:53 PM [ExceptionsHandler] Cannot read property 'getUser' of undefined
TypeError: Cannot read property 'getUser' of undefined
Hi @alexcorvi,
Can you paste your code here? With Typescript, Nest should deduce dependency just by type.
Hi all,
For my use case I had to use @Inject() parameter decorator instead of @Dependencies():
import {Controller, Inject, RequestMapping, RequestMethod} from 'nest.js';
import {UserService} from './user.service';
@Controller({ path: 'users'})
export class UserController {
constructor(@Inject(UserService) private userService) {}
@RequestMapping()
public async getAllUsers(request, response) {
const users = await this.userService.getAllUsers();
response.status(200).json(users);
}
@RequestMapping({ path: '/:id' })
public async getUser(request, response) {
const user = await this.userService.getUser(request.params.id);
response.status(200).json(user);
}
@RequestMapping({ method: RequestMethod.POST })
public async addUser(request, response) {
const message = await this.userService.addUser(request.body.user);
response.status(201).json(message);
}
}
I use the 1.0.0-rc8
Hi @ThomRick,
Let's try:
constructor(private userService: UserService) {}
With Typescript, it should works. If not - it is an issue.
import {Dependencies,RequestMethod,Controller,RequestMapping} from 'nest.js';
import {Request,Response,NextFunction} from "@types/express"
import {UsersService} from "./users.service";
import {UserRequest} from "./user.typing";
@Controller({path: 'users'})
export class UsersController {
constructor(private usersService: UsersService) {
console.log(usersService,this.usersService);
}
@RequestMapping()
async getAllUsers(req:UserRequest, res:Response) {
const users = await this.usersService.getAllUsers();
res.status(200).json(users);
}
@RequestMapping({ path: '/:id' })
async getUser(req:UserRequest, res:Response) {
console.log(req.params.id);
const user = await this.usersService.getUser(req.params.id);
res.status(200).json(user);
}
@RequestMapping({ method: RequestMethod.POST })
async addUser(req:UserRequest, res:Response) {
const msg = await this.usersService.getUser(req.body.user);
res.status(201).json(msg);
}
}
Component()
export class UsersService {
private users = [
{ id: 1, name: "John Doe" },
{ id: 2, name: "Alex Corvi" },
{ id: 3, name: "Who Knows" },
];
async getAllUsers():Promise<User[]> {
return await this.users;
}
async getUser(id: string):Promise<User> {
const user = this.users.find((user) => user.id.toString() === id);
if (!user) throw new HttpException("User not found", 404);
return await user;
}
async addUser(user:User):Promise<UserAdded> {
this.users.push(user);
return await {
id:user.id,
name:user.name,
date:new Date().getTime()
};
}
}
import {Module} from 'nest.js';
import {UsersController} from './users.controller';
import {UsersService} from './users.service';
@Module({
controllers: [ UsersController ],
components: [ UsersService ],
})
export class UsersModule {}
Now when running ts-node src/server.ts Here's the output:
[Nest] 712 - 4/12/2017, 10:43:56 PM [NestFactory] Starting Nest application...
[Nest] 712 - 4/12/2017, 10:43:56 PM [InstanceLoader] ApplicationModule dependencies initialized
undefined undefined
[Nest] 712 - 4/12/2017, 10:43:56 PM [InstanceLoader] UsersModule dependencies initialized
[Nest] 712 - 4/12/2017, 10:43:56 PM [RoutesResolver] UsersController:
[Nest] 712 - 4/12/2017, 10:43:56 PM [RouterBuilder] Mapped {/, GET} route
[Nest] 712 - 4/12/2017, 10:43:56 PM [RouterBuilder] Mapped {/:id, GET} route
[Nest] 712 - 4/12/2017, 10:43:56 PM [RouterBuilder] Mapped {/, POST} route
[Nest] 712 - 4/12/2017, 10:43:56 PM [NestApplication] Nest application is ready!
Navigating to localhost:3000/users gives the following error in the console:
[Nest] 712 - 4/12/2017, 10:52:53 PM [ExceptionsHandler] Cannot read property 'getAllUsers' of undefined
TypeError: Cannot read property 'getAllUsers' of undefined
@alexcorvi - please, show your tsconfig.json file.
{
"compilerOptions": {
"module": "commonjs",
"target": "es6",
"noImplicitAny": true,
"sourceMap": false,
"strictNullChecks": true,
"experimentalDecorators": true,
"outDir": "./dist/"
},
"exclude": ["node_modules"],
"files": ["./src/server.ts"]
}
Here's a full repo: https://github.com/alexcorvi/typescript-dependency-management-issue
Hey @kamilmysliwiec,
Sorry it doesn't work without the @Inject() decorator :-/
I try to log what happened in the UserController constructor:
Without @Inject() decorator:
[Nest] 3931 - 2017-04-13 08:52:16 [NestFactory] Starting Nest application...
- - - - UserController constructor - - - -
undefined
- - - - UserController constructor - - - -
[Nest] 3931 - 2017-04-13 08:52:16 [InstanceLoader] ApplicationModule dependencies initialized
[Nest] 3931 - 2017-04-13 08:52:16 [RoutesResolver] UserController:
[Nest] 3931 - 2017-04-13 08:52:16 [RouterBuilder] Mapped {/, GET} route
[Nest] 3931 - 2017-04-13 08:52:16 [RouterBuilder] Mapped {/:id, GET} route
[Nest] 3931 - 2017-04-13 08:52:16 [RouterBuilder] Mapped {/, POST} route
[Nest] 3931 - 2017-04-13 08:52:16 [NestApplication] Nest application is ready!
Application is listening at port 8080
With the @Inject() decorator:
[Nest] 3937 - 2017-04-13 08:52:42 [NestFactory] Starting Nest application...
- - - - UserController constructor - - - -
UserService {
users:
[ { id: '1', name: 'John Doe' },
{ id: '2', name: 'Alice Cairo' },
{ id: '3', name: 'Who Knows' } ] }
- - - - UserController constructor - - - -
[Nest] 3937 - 2017-04-13 08:52:42 [InstanceLoader] ApplicationModule dependencies initialized
[Nest] 3937 - 2017-04-13 08:52:42 [RoutesResolver] UserController:
[Nest] 3937 - 2017-04-13 08:52:42 [RouterBuilder] Mapped {/, GET} route
[Nest] 3937 - 2017-04-13 08:52:42 [RouterBuilder] Mapped {/:id, GET} route
[Nest] 3937 - 2017-04-13 08:52:42 [RouterBuilder] Mapped {/, POST} route
[Nest] 3937 - 2017-04-13 08:52:42 [NestApplication] Nest application is ready!
Hey @smsites,
You find the right solution to the issue with the "emitDecoratorMetadata": true
Let's see my tsconfig.json :
{
"compilerOptions": {
"module": "commonjs",
"target": "es6",
"sourceMap": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"outDir": "dist",
"typeRoots": [
"node_modules/@types"
]
},
"include": [
"src/**/*"
],
"exclude": [
"node_modules"
]
}
And the UserController class code:
import {Controller, RequestMapping, RequestMethod} from 'nest.js';
import {UserService} from './user.service';
@Controller({ path: 'users'})
export class UserController {
constructor(private userService: UserService) {
console.log('- - - - UserController constructor - - - -');
console.log('UserService : ', this.userService);
console.log('- - - - UserController constructor - - - -');
}
@RequestMapping()
public getAllUsers(request, response) {
this.userService.getAllUsers()
.then(users => {
response.status(200).json(users);
});
}
@RequestMapping({ path: '/:id' })
public getUser(request, response) {
this.userService.getUser(request.params.id)
.then(user => {
response.status(200).json(user);
});
}
@RequestMapping({ method: RequestMethod.POST })
public addUser(request, response) {
this.userService.addUser(request.body.user)
.then(message => {
response.status(201).json(message);
});
}
}
No need the @Inject() param decorator.
Hi @alexcorvi @ThomRick,
Let's add:
"emitDecoratorMetadata": true,
to your tsconfig.json file. It is my mistake - I didn't mention about it in the documentation.
EDIT: I answered using my old account.
@kamilmysliwiec Confirmed, this solved it for me.
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Most helpful comment
Hi @alexcorvi @ThomRick,
Let's add:
to your
tsconfig.jsonfile. It is my mistake - I didn't mention about it in the documentation.EDIT: I answered using my old account.