Must there provide a name for @Service and @Inject?
Diluka opened this issue ยท 12 comments
I use empty @Service()
and @Inject()
, so raise an error TypeError: Cannot read property 'bind' of undefined
I add a name to both then they work fine.
typedi 0.4.2
node 6.2.1
can you provide a code sample?
todo.controller.ts
import {Get, Post, UseInterceptor, Body, Controller} from "routing-controllers";
import {TodoService} from "../service/todo.service";
import {Inject} from "typedi";
import * as _ from "lodash";
import * as AV from "leanengine";
@Controller("/todos")
export class TodoController {
@Inject() private todoService:TodoService;
@Get("/")
@UseInterceptor((req, res, content) => {
if (_.isArray(content)) {
return _.map(content, (o:AV.Object) => o.toJSON());
}
return content;
})
getAll() {
return this.todoService.getAll();
}
// @Post("/")
// post(@Body() data) {
// return this.todoService.save(data);
// }
}
todo.service.ts
import * as AV from "leanengine";
import {Service} from "typedi";
import {Todo} from "../entity";
@Service()
export class TodoService {
getAll() {
return new AV.Query(Todo).find<AV.Object[]>();
}
save(data) {
return new Todo(data).save<AV.Object>();
}
}
app.ts
import "reflect-metadata";
import {createExpressServer, useContainer} from "routing-controllers";
import {Container} from "typedi";
import * as Express from "express";
import * as AV from "leanengine";
// load all services
import "./service";
useContainer(Container);
export const app: Express.Application = createExpressServer({
controllerDirs: [__dirname + "/controller/*.controller.js"]
});
app.use(AV.express());
error stack
TypeError: Cannot read property 'bind' of undefined
at Function.Container.get (D:\Users\Diluka\Documents\GitHub\leancloud-demo\node_modules\.npminstall\typedi\0.4.2\typedi\Container.js:64:39)
at Object.Container_1.Container.registerPropertyHandler.getValue (D:\Users\Diluka\Documents\GitHub\leancloud-demo\node_modules\.npminstall\typedi\0.4.2\typedi\decorators.js:31:70)
at D:\Users\Diluka\Documents\GitHub\leancloud-demo\node_modules\.npminstall\typedi\0.4.2\typedi\Container.js:110:40
at Array.forEach (native)
at Function.Container.applyPropertyHandlers (D:\Users\Diluka\Documents\GitHub\leancloud-demo\node_modules\.npminstall\typedi\0.4.2\typedi\Container.js:105:14)
at Function.Container.get (D:\Users\Diluka\Documents\GitHub\leancloud-demo\node_modules\.npminstall\typedi\0.4.2\typedi\Container.js:66:14)
at Object.getFromContainer (D:\Users\Diluka\Documents\GitHub\leancloud-demo\node_modules\.npminstall\routing-controllers\0.6.2\routing-controllers\container.js:36:42)
at ControllerMetadata.Object.defineProperty.get [as instance] (D:\Users\Diluka\Documents\GitHub\leancloud-demo\node_modules\.npminstall\routing-controllers\0.6.2\routing-controllers\metadata\
ControllerMetadata.js:27:32)
at ActionMetadata.executeAction (D:\Users\Diluka\Documents\GitHub\leancloud-demo\node_modules\.npminstall\routing-controllers\0.6.2\routing-controllers\metadata\ActionMetadata.js:258:39)
at D:\Users\Diluka\Documents\GitHub\leancloud-demo\node_modules\.npminstall\routing-controllers\0.6.2\routing-controllers\RoutingControllerExecutor.js:74:33
@Diluka how to reproduce this error in your demo? Im running node ./dist/app.js
and have no issue (p.s. i added ("emitDecoratorMetadata": true and "experimentalDecorators": true)
to your tsconfig.json)
@pleerock Sorry for commenting on a closed issue, but I'm also having this exact issue - example repo here: https://github.com/mogusbi/typedi-error
Whenever I hit my routing-controller
endpoint, I'm met with this error
{
"name": "TypeError",
"message": "Cannot read property 'readAll' of undefined",
"stack": "TypeError: Cannot read property 'readAll' of undefined\n at QuestionController.httpGetAll (/Volumes/Data/Users/mo/Desktop/typeorm/src/controllers/question/question.controller.ts:11:32)\n at ActionMetadata.callMethod (/Volumes/Data/Users/mo/Desktop/typeorm/src/metadata/ActionMetadata.ts:254:62)\n at /Volumes/Data/Users/mo/Desktop/typeorm/src/RoutingControllers.ts:123:142"
}
Here's a quick recap of my code
// question.controller.ts
import {Body, Delete, Get, HttpCode, JsonController, Param, Post, Put} from 'routing-controllers';
import {Inject} from 'typedi';
import {IQuestion, Question, QuestionService} from '../../entities/question';
@JsonController('/question')
export class QuestionController {
@Inject() private questionService: QuestionService;
@Get()
public httpGetAll (): Promise<[Question[], number]> {
return this.questionService.readAll();
}
@Get('/:id')
public httpGetOne (
@Param('id') id: string
): Promise<Question> {
return this.questionService.readOne(id);
}
@Post()
@HttpCode(201)
public httpPost (
@Body({
required: true
}) props: IQuestion
): Promise<Question> {
return this.questionService.create(props);
}
@Put('/:id')
public httpPut (
@Param('id') id: string,
@Body({
required: true
}) props: IQuestion
): Promise<void> {
return this.questionService.update(id, props);
}
@Delete('/:id')
public httpDelete (
@Param('id') id: string
): Promise<void> {
return this.questionService.drop(id);
}
}
// question.service.ts
import {Service} from 'typedi';
import {Repository} from 'typeorm';
import {OrmRepository} from 'typeorm-typedi-extensions';
import {IQuestion} from './question.interface';
import {Question} from './question.model';
@Service()
export class QuestionService {
@OrmRepository(Question) private repository: Repository<Question>;
public create (props: IQuestion): Promise<Question> {
return this.repository.persist(props);
}
public readAll (size: number = 10, page: number = 1): Promise<[Question[], number]> {
const skip: number = size * (page - 1);
return this.repository.findAndCount({
skip,
take: page
});
}
public readOne (id: string): Promise<Question> {
return this.repository.findOneById(id);
}
public update (id: string, props: IQuestion): Promise<void> {
return this.repository.updateById(id, props);
}
public drop (id: string): Promise<void> {
return this.repository.removeById(id);
}
}
// www.ts
import * as http from 'http';
import 'reflect-metadata';
import {Container} from 'typedi';
import {createConnection, useContainer} from 'typeorm';
import {config} from '../config';
import {BaseEntity, Question} from '../entities';
import {app} from './app';
useContainer(Container);
createConnection({
...config.sql,
entities: [
BaseEntity,
Question
]
}).then(
() => http
.createServer(app)
.listen(8082, () => console.log('Server started on port 8082'))
).catch(
(err: Error) => console.error(err.message)
);
// tsconfig.json
{
"compilerOptions": {
"declaration": false,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"importHelpers": true,
"lib": [
"es2015",
"es2016"
],
"module": "commonjs",
"moduleResolution": "node",
"noEmitHelpers": true,
"noImplicitAny": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"removeComments": true,
"skipLibCheck": true,
"sourceMap": true,
"suppressImplicitAnyIndexErrors": true,
"target": "es5"
},
"awesomeTypescriptLoaderOptions": {
"useWebpackText": true
}
}
I am running typescript 2.4.1 and node 6.10.2
@mogusbi Hey, found out by looking at the @Diluka bug report code.
You certainly forgot :
import { Container } from "typedi";
import { useContainer } from 'routing-controllers';
useContainer(Container);
To place into your app.ts
. It tells to routing-controllers to use the container from typeDI.
See this file.
@pleerock maybe it should appear somewhere in a "Troubleshooting" section or whatever ? I know this is related to routing-controller or whatever lib we use in complement of TypeDI, but I think a great number of developers may face this at some point. Idk, what you think ?
yeah we can add links in Troubleshooting section, like this:
Troubleshooting
- how to use TypeDI with TypeORM
- how to use TypeDI with routing-controllers
...
with links to appropriate qa. PRs are welcomed
Thank you!
This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.