typefox / djinject Goto Github PK
View Code? Open in Web Editor NEWDependency injection done right.
License: MIT License
Dependency injection done right.
License: MIT License
Djinject version: 0.3.2
If the service is a provider (read: function), the current Module type definition allows curried functions of arbitrary depth.
type C = { a: () => number }
type M = Module<C>
const m: M = { a: () => () => () => () => 1 }
Link to code example:
Compiles all of the following:
const m1: M = {
a: () => 1
}
const m2: M = {
a: () => () => 1
}
const m3: M = {
a: () => () => () => 1
}
Should compile only m2
(see above).
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> ? ... : ...
?
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
}
};
}
Type Module<T, T>
only allows values of type { group: { Service: () => I } }
Type Module<T, T>
allows type { group: { Service: () => I | undefined } }
{ g?: { s: () => T } }
{ g: { s?: () => T } }
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>;
Arrow function/factory parameter ctx
is inferred to any
Arrow function/factory parameter ctx
is inferred to Context & Dependencies
I am not sure if this is a bug 🐞… during module writing, I miss type information of the factory parameter (this line for example). Instead it displays ANY… what is wrong in my module definition?
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?
npm run build
lib/inject.d.ts
A compiler error occurs "A rest parameter must be of an array type."
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.
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>;
Type of x
is
{
group: never
}
Type of x
is
{
group: {
Service1: I1,
Service2: I2
}
}
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!'
});
});
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
})
}
}
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?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.