Inversifyjs: Extending functionallity

Created on 14 Nov 2016  路  8Comments  路  Source: inversify/InversifyJS

I would like to extend the functionality of some classes.
For example, I would like to automatically create a child from a container.

Normally I would do something like this:

import { Container } from 'inversify';

Container.prototype.createChild = () => {
  const child = new Container();
  child.parent = this;
  return child;
};

declare module 'inversify' {
  interface Container {
    createChild: Container;
  }
}

This is not working:

node_modules/inversify/dts/inversify.d.ts(1,10): error TS2484: Export declaration conflicts with exported declaration of 'Container'
server/src/modules/prj/core/di.ts(3,1): error TS2304: Cannot find name 'Container'.
server/src/modules/prj/core/di.ts(4,21): error TS2304: Cannot find name 'Container'.

I guess something is special in the way the d.ts files are created since it is easily possible in rxjs

See this sample

question

All 8 comments

Can you please try class based inheritance:

interface CustomContainer extends interfaces.Container {
    createChild: Container;
}

class CustomContainer  extends Container {
    createChild = () => {
        const child = new Container();
        child.parent = this;
        return child;
    }
}

I have't try this but I assume that it will work. Please let me know if it solves your problem :wink:

Thank you for the quick response, great work btw!!!

Inheriting will work, but it doesn't fit my use case (lib) it's more for local use.
If I go that path I will have to force user's of my lib to use my Container version, which is a bad idea.

I'm also not a fan of monkey patching but if it's harmless I can live with it.

Patching the prototype while extending the type the way I tried to is the official way to do it as described in the TypeScript docs here (see Module Augmentation)

I think the reason it's not working is due to the use of default exports.
Also the main file is renaming (as) all the defaults which might also be a problem.

I also tried:

declare module 'inversify/dts/container/container' {
  interface Container {
    createChild(): Container;
  }
}

With no luck, there is no Container interface in the module since the module is the Container (default)

I believe default is not a good pattern, RXJS doesn't use it, angular 2 does not as well and they are 2 leading TypeScript projects...

It doesn't save much anyway...

BTW, creating a child from the parent directly is a good addition, that helper function makes sense a parent creating a child...

Interesting :thinking: do you know about any issue/link in which I can learn more about the default exports issues? I want to learn more before I introduce a change.

I will introduce Container.prototype.createChild as a feature. I have create #408 to track it. Feel free to send a PR.

Well, Axel Rauschmayer from the @2ality blog commented about it, he's someone to listen to...

You can also read a very good explanation here

I don't see any good reasons to use default exports, it doesn't give anything really, saves nothing.
You can also see that my attempt to augment the module failed and it shouldn't, I did it "by the books"

@lholznagel thanks.

There are more reasons that devs didn't find yet, I think this issue is on more reason... I'm 99% sure its due to default exports.

I would ban them personally :)

@shlomiassaf @lholznagel thanks a lot for the links!

I have created another issue to remove the default exports #410 I'm closing this issue because now we can use #408 & #410 to track the required actions.

@shlomiassaf thanks a lot for trying the beta and sharing feedback it is a really valuable contribution :+1:

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ashraymehta picture ashraymehta  路  3Comments

remojansen picture remojansen  路  4Comments

remojansen picture remojansen  路  4Comments

hexa00 picture hexa00  路  3Comments

RastriginSergey picture RastriginSergey  路  3Comments