Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Typescript error with async factories #83

Closed
Ackos95 opened this issue Mar 1, 2018 · 3 comments
Closed

Typescript error with async factories #83

Ackos95 opened this issue Mar 1, 2018 · 3 comments

Comments

@Ackos95
Copy link
Contributor

Ackos95 commented Mar 1, 2018

I've been trying to create async app initialization using awilix. As container doesn't support async factories I've used pattern recommended here, but typescript trows an error if I try to destruct dependencies in factory function declaration.

Example:

const createContainer = async (): AwilixContainer => {
  const container: AwilixContainer = createContainer();

  const config: TConfigOptions = { dbOptions: { /* ... */ } };
  container.register('config', asValue(config));

  // passing cradle to ensure dependencies inside factory
  const db = await asyncDbFactory(container.cradle);
  container.register('db', asValue(db));
  // rest of the code
}

// db factory
// For this destruction I receive error for type missmatch
// `{ [key: string]: any }` doesn't match `{ config: TConfigOptions }`
const asyncDbFactory = ({ config }: { config: TConfigOptions }) =>
  new Promise((resolve: (db: TDb) => void) => {
    // connection logic

    // resolve(db);
  })

It does work properly if I don't define types in asyncDbFactory

// this way typescript won't mind
const asyncDbFactory(opts: any) => /* ... */

Is there a way to bypass this that I'm not seeing or is it just a price we must pay?

@Ackos95
Copy link
Contributor Author

Ackos95 commented Mar 1, 2018

If I may suggest simple solution. It can be done by modifying type of container.cradle into any, I know that sounds counter-intuitive but it would enable to manually define type of dependencies and to cast cradle into it when invoking. In previous example it would look something like this:

const createContainer = async (): AwilixContainer => {
  const container: AwilixContainer = createContainer();

  const config: TConfigOptions = { dbOptions: { /* ... */ } };
  container.register('config', asValue(config));

  // passing cradle to ensure dependencies inside factory
  const db = await asyncDbFactory(container.cradle as { config: TConfigOptions });
  container.register('db', asValue(db));
  // rest of the code
}

// db factory
// No error anymore
const asyncDbFactory = ({ config }: { config: TConfigOptions }) =>
  new Promise((resolve: (db: TDb) => void) => {
    // connection logic

    // resolve(db);
  })

I'm aware that this is not a perfect solution, but current cradle type doesn't give much information, and yet it blocks any casting.

@jeffijoe
Copy link
Owner

jeffijoe commented Mar 1, 2018

I'm fine with that. 😄

As a tip, you can actually use a double cast to get around this:

container.cradle as any as { config: TConfigOptions }

I'll merge your PR and release.

jeffijoe added a commit that referenced this issue Mar 1, 2018
[#83] Changed cradle typing into  to enable casting
@jeffijoe
Copy link
Owner

jeffijoe commented Mar 1, 2018

Released as v3.0.6, thanks!

@jeffijoe jeffijoe closed this as completed Mar 1, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants