Giter Site home page Giter Site logo

djinject's People

Contributors

danieldietrich avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

Forkers

moltar

djinject's Issues

Module type definition allows curried functions of arbitrary depth

Bug Report

Djinject version: 0.3.2

If the service is a provider (read: function), the current Module type definition allows curried functions of arbitrary depth.

Steps To Reproduce

  1. Set type C = { a: () => number }
  2. Set type M = Module<C>
  3. Set const m: M = { a: () => () => () => () => 1 }

Link to code example:

TypeScript Playground

The current behavior

Compiles all of the following:

const m1: M = {
    a: () => 1
}

const m2: M = {
    a: () => () => 1
}

const m3: M = {
    a: () => () => () => 1
}

The expected behavior

Should compile only m2 (see above).

Proposed fix

type Module<C = any, T = C> = {
    [K in keyof T]: T[K] extends Fn ? Factory<C, T[K]> : (Module<C, T[K]> | Factory<C, T[K]>)
}

Question: with the above Module definition, do inferred types still work, e.g. ... extends Module<unknown, infer T> ? ... : ...?

Module type casts optional service to required service

Bug Report

Djinject version: 0.5.0

interface I {
    b: boolean
}

type T = {
    group: {
        Service?: I
    }
}

function _(i: I | undefined): Module<T, T> {
    return {
        group: {
            Service: () => i // ERROR: Type 'undefined' is not assignable to type 'I'.ts(2322)
        }
    };
}

Workaround:

function _(i: I | undefined): Module<T, T> {
    return {
        group: {
            Service: () => i! // force type I
        }
    };
}

The current behavior

Type Module<T, T> only allows values of type { group: { Service: () => I } }

The expected behavior

Type Module<T, T> allows type { group: { Service: () => I | undefined } }

Factory parameter is any context and dependency types are not distinct

Bug Report

Djinject version: 0.5.0

interface I1 {
    b: boolean
}

interface I2 {
    n: number
}

type Dependencies = {
    group: {
        Service1: I1
    }
}

type Context = {
    group: {
        Service2: I2
    }
}

const x = {
    group: {
        Service1: (ctx) => { // ERROR: Parameter 'ctx' implicitly has an 'any' type.ts(7006)
            b: ctx.group.Service2.n === 0
        }
    }
} satisfies Module<Context & Dependencies, Dependencies>;

Workaround:

const x = {
    group: {
        Service1: (ctx) => { // ctx has correct type
            b: ctx.group.Service2.n === 0
        }
    }
} satisfies Module<Context & Dependencies>;

The current behavior

Arrow function/factory parameter ctx is inferred to any

The expected behavior

Arrow function/factory parameter ctx is inferred to Context & Dependencies

lib/inject.d.ts of the bundled application does not compile

Bug Report

Djinject version: 0.9.0

lib/inject.d.ts of the bundled application does not compile because ts-expect-error was removed. Does it work for consumers of djinject?

Steps To Reproduce

  1. npm run build
  2. Open lib/inject.d.ts

The current behavior

A compiler error occurs "A rest parameter must be of an array type."

The expected behavior

If the use-site does not receive an error and the app that uses Djinject compiles/bundles fine, then the current behavior is ok.

Otherwise, the original comment that instruct the compiler to ignore the error needs to be part of the compiler output.

Type is never if two distinct module groups are merged

Bug Report

Djinject version: 0.5.0

The following code is expected to work but currently does not compile:

interface I1 {
    b?: boolean
}

interface I2 {
    n: number
}

type Dependencies = {
    group: {
        Service1?: I1
    }
}

type Context = {
    group: {
        Service2: I2
    }
}

// ERROR: Type '{ Service1: () => I1; }' is not assignable to type 'never'.ts(2322)
export const x = {
    group: {
        Service1: () => ({
            b: true
        })
    }
} satisfies Module<Context, Dependencies>;

Workaround:

export const x = {
    group: {
        Service1: () => ({
            b: true
        })
    }
} satisfies Module<Context & Dependencies>;

The current behavior

Type of x is

{
    group: never
}

The expected behavior

Type of x is

{
    group: {
        Service1: I1,
        Service2: I2
    }
}

Check context type

The context ctx of a factory function should be a non-primitive type.

The following test should succeed (read: inject should emit a compiler error):

it('should disallow to use wrong context types', () => {
    // @ts-expect-error Wrong context type
    inject({
        hi: (ctx: false) => 'Hi!'
    });
});

Support eager initialization of whole Module groups

Currently it is possible to eagerly initialize services:

const module = {
   group: {
       subgroup: {
           eagerService1: eager(() => void),
           eagerService2: eager(() => void)
       }
   }
}

As a user of djinject, I want be able to eagerly initialize whole (sub-)groups. That way, the eager initialization will also take place if we rebind an existing service with one which is lazily evaluated by default:

const module = {
   group: {
       subgroup: eager({
           eagerService1: () => void,
           eagerService2: () => void
       })
   }
}

Dependency graph visualization

I started using djinject here. I splitted a lot of utility classes into multiple groups, which is quite nice against cognitive overload. But now I have no overview about dependencies.

Is there a way to list the edges „A gets called by B“? It should not really be a main feature, but something like a extension. I would volunteer for creating a prototype, if you have other things to do :-).

My approach would be to get the module and then call every factory… like eager loading. But then I will need some help I think. Maybe a own inject function? To mimic the Proxy pattern?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.