inversify / InversifyJS

A powerful and lightweight inversion of control container for JavaScript & Node.js apps powered by TypeScript.
http://inversify.io/
MIT License
11.33k stars 719 forks source link

Attributes don't compile in Typescript? #62

Closed RichardJECooke closed 8 years ago

RichardJECooke commented 8 years ago

*I put this question on Stackoverflow, but there's no InversifyJS tag there yet: http://stackoverflow.com/questions/35149514/why-does-inversifyjs-not-compile-this-attribute

I'm copying the Inversify documentation almost exactly (version 1.2.2) and it fails to compile, giving me Typescript error TS1238. Why?

'use strict';
import './tools/typescriptImports';
import IServer = require('./iServer.ts');
import IDatabase = require('../database/iDatabase');
import express = require('express');
import bodyParser = require('body-parser');
import config = require('../config');
import types = require('../tools/types.ts');
import _ = require('lodash');
import async_ = require('async');
import { Inject } from "inversify";

@Inject("IDatabase") // <- error TS1238: Unable to resolve signature of class decorator when called as an expression. Supplied parameters do not match any signature of call target.
class Server implements IServer
{
    db : IDatabase;
    expressApp : express.Express;

    constructor(db : IDatabase)
    {
        this.db = db;
        ..
RichardJECooke commented 8 years ago

And my other code in case it helps:

iDatabase.ts:

'use strict'

interface IDatabase
{
    deleteAllBooks() : any;
    insertBook(name: string, src: string) : any;
    selectBook() : any;
}

export = IDatabase;

database.ts:

'use strict'
import { Inject } from "inversify";
import IDatabase = require("./iDatabase");
import pgp = require('pg-promise');
import config = require('../config');

//https://github.com/vitaly-t/pg-promise/wiki/Learn-by-Example
class Database implements IDatabase
{
    _db : any;

    constructor ()
    {
        this._db = pgp(/*options*/)(config.divi_db_connectionstring); //connect to database
    }

    deleteAllBooks() : any
    {
        return this._db.query("delete from dbo.note", null, null);
    }

    insertBook(name: string, src: string) : any
    {
        return this._db.none("insert into dbo.note(name, src) values($1, $2)", [name, src]);
    }

    selectBook() : any
    {
        return this._db.query("select name, src from dbo.note", null);
    }

}

export = Database;

ioc.ts:

'use strict';
import { TypeBinding, Kernel, TypeBindingScopeEnum } from "inversify";
import IDatabase = require('../database/iDatabase');
import Database = require('../database/database');
import IServer = require('../webservice/iServer');
import Server = require('../webservice/server');

//http://inversify.io
class Ioc
{
    public container : Kernel;

    constructor()
    {
        let c = new Kernel();
        c.bind(new TypeBinding<IDatabase>("IDatabase", Database, TypeBindingScopeEnum.Transient));
        c.bind(new TypeBinding<IServer>("IServer", Server, TypeBindingScopeEnum.Transient));
        //c.bind(new TypeBinding<ISettings>("ISettings", Settings, TypeBindingScopeEnum.Singleton));
        this.container = c;
    }
}

export = Ioc;
remojansen commented 8 years ago

The answer by John White is right:

You can use:

class Server implements IServer
{
    db : IDatabase;
    expressApp : express.Express;

    constructor(@Inject("IDatabase") db : IDatabase)
    {
        this.db = db;
        ...
    }
}

But it will stop working in the next release:

@Inject("IDatabase")
class Server implements IServer
{
    db : IDatabase;
    expressApp : express.Express;

    constructor(db : IDatabase)
    {
        this.db = db;
        ...
    }
}

Sorry about the misleading docs...

remojansen commented 8 years ago

Hi @RichardJECooke I just released version 1.3.0 and it allows to apply the Inject decorator to a class:

interface IKatana {
    power : number;
    hit() : boolean;
}

interface IShuriken {
    power : number;
    throw() : boolean;
}

@Inject("IKatana", "IShuriken")
class Warrior {

    private _katana : IKatana;
    private _shuriken : IShuriken;

    constructor(katana : IKatana, shuriken : IShuriken) {
        this._katana = katana;
        this._shuriken = shuriken;
    }
}

The following is not supported anymore:

class Warrior {

    private _katana : IKatana;
    private _shuriken : IShuriken;

    constructor(
        @Inject("IKatana") katana : IKatana, 
        @Inject("IShuriken") shuriken : IShuriken
    ) {
        this._katana = katana;
        this._shuriken = shuriken;
    }
}

Sorry about the issues caused.