Comments (6)
The same for me.
I have random Type instantiation is excessively deep and possibly infinite.
errors encountered after adding one extra provideFactory
.
from typed-inject.
It was a disaster, I spent a lot of time understanding what was happening with VSCode and eventually, I found this issue.
I really like this library but my project got stuck when the number of provideClass came to 20. I really don't know what to do.
Are there any ways to resolve this issue? Or I should refactor the whole project using another library?(((
from typed-inject.
Would a non-chainable API help you here? I mean, don't you have dependencies that depend on each other?
I.e. would you expect something like this to work?
interface Foo {
foo: string;
}
class Bar {
static readonly inject = ['foo'] as const;
constructor(foo: Foo){ }
}
rootInjector.provide({
foo: { value: { foo: 'hello'} },
bar: { clazz: Bar }
})
Because something like that might be impossible to get statically type-checked.
from typed-inject.
Thanks for the response @nicojs. I see what you are saying. I actually took a stab at this today except using a proxy so I could do stuff like container.dep instead of container.resolve("dep"). The most type safe I could get it is was where the inject tokens had to be part of the keys passed in, and that the factory func args had to at least be one of the resulting types of the factory functions (or static values). It would be great to somehow link the args names to a type. When I have more time I may dig deeper into how you were doing your typing to understand if this is possible but I've kind of got something that unblocks me and has "better than nothing" typing lol. Here is what I ended up with if you are interested:
type AsContainerWithInstanceTypes<TIn extends Record<string, ((...args: any) => any) | { value: any }>> = {
[prop in keyof TIn as prop]: TIn[prop] extends { value: any }
? TIn[prop]["value"]
: TIn[prop] extends (...args: any) => any
? ReturnType<TIn[prop]>
: unknown;
};
export function createDiContainer<
T extends Record<
string,
| (((...args: AsContainerWithInstanceTypes<T>[keyof AsContainerWithInstanceTypes<T>][]) => any) & {
inject?: readonly (keyof T)[];
})
| { value: any }
>,
>(
dependencies: T,
options?: { logger?: Logger; onResolve?: (prop: string, val: any) => void },
): AsContainerWithInstanceTypes<T> {
const _containerCache: Map<string, any> = new Map();
const _onResolve = (prop: string, val: any) => {
if (options?.onResolve) {
options?.onResolve(prop, val);
}
_containerCache.set(prop, val);
options?.logger?.debug(`returning ${prop} for first time`);
return val;
};
const handler = {
get: function (target: any, prop: string, receiver: any) {
options?.logger?.debug(`resolving ${prop}`);
if (_containerCache.has(prop)) {
options?.logger?.debug(`returning ${prop} from cache`);
return _containerCache.get(prop);
}
const targetDep = dependencies[prop];
if (!targetDep) {
throw new Error(`dependency "${prop}" not registered with container!`);
}
// TODO: implement classes. -mc
if (!_.isFunction(targetDep)) {
const resolved = targetDep.value;
return _onResolve(prop, resolved);
}
const paramNames = (targetDep as any).inject || [];
options?.logger?.debug(
`${prop} has ${paramNames.length === 0 ? "no dependencies" : `dependencies: ${paramNames.join(", ")}`}`,
);
const params = paramNames.map((dep: string) => this.get(target, dep, receiver));
const resolved = targetDep(...params);
return _onResolve(prop, resolved);
},
};
return new Proxy(dependencies, handler);
}
from typed-inject.
Chiming in to say that I got the same error as @fobdy on my 21st .provideXXXXXX
.
from typed-inject.
The provideXxx
method chains create heavily nested TChildContext
.
So I patched to Injector
type to flatten type as follows:
diff --git a/node_modules/typed-inject/dist/src/api/Injector.d.ts b/node_modules/typed-inject/dist/src/api/Injector.d.ts
index 9375bb6..49fed38 100644
--- a/node_modules/typed-inject/dist/src/api/Injector.d.ts
+++ b/node_modules/typed-inject/dist/src/api/Injector.d.ts
@@ -2,13 +2,14 @@ import { InjectableClass, InjectableFunction } from './Injectable';
import { InjectionToken } from './InjectionToken';
import { Scope } from './Scope';
import { TChildContext } from './TChildContext';
export interface Injector<TContext = {}> {
injectClass<R, Tokens extends readonly InjectionToken<TContext>[]>(Class: InjectableClass<TContext, R, Tokens>): R;
injectFunction<R, Tokens extends readonly InjectionToken<TContext>[]>(Class: InjectableFunction<TContext, R, Tokens>): R;
resolve<Token extends keyof TContext>(token: Token): TContext[Token];
- provideValue<Token extends string, R>(token: Token, value: R): Injector<TChildContext<TContext, R, Token>>;
- provideClass<Token extends string, R, Tokens extends readonly InjectionToken<TContext>[]>(token: Token, Class: InjectableClass<TContext, R, Tokens>, scope?: Scope): Injector<TChildContext<TContext, R, Token>>;
- provideFactory<Token extends string, R, Tokens extends readonly InjectionToken<TContext>[]>(token: Token, factory: InjectableFunction<TContext, R, Tokens>, scope?: Scope): Injector<TChildContext<TContext, R, Token>>;
+ provideValue<Token extends string, R>(token: Token extends keyof TContext ? never : Token, value: R): Injector<{ [K in keyof TContext]: TContext[K]} & { [T in Token]: R }>;
+ provideClass<Token extends string, R, Tokens extends readonly InjectionToken<TContext>[]>(token: Token extends keyof TContext ? never : Token, Class: InjectableClass<TContext, R, Tokens>, scope?: Scope): Injector<{ [K in keyof TContext]: TContext[K]} & { [T in Token]: R }>;
+ provideFactory<Token extends string, R, Tokens extends readonly InjectionToken<TContext>[]>(token: Token extends keyof TContext ? never : Token, factory: InjectableFunction<TContext, R, Tokens>, scope?: Scope): Injector<{ [K in keyof TContext]: TContext[K]} & { [T in Token]: R }>;
dispose(): Promise<void>;
}
//# sourceMappingURL=Injector.d.ts.map
\ No newline at end of file
// argument (to prevent from providing value with same token)
token: Token
// ↓
token: Token extends keyof TContext ? never : Token
// return type
Injector<TChildContext<TContext, R, Token>>
// ↓
Injector<{ [K in keyof TContext]: TContext[K]} & { [T in Token]: R }>;
https://github.com/nasuboots/typed-inject-types
Then I can chain the methods up to 49 without error. Also, it makes very faster to resolve type checking.
Over 49 method chains cause error: "Type instantiation is excessively deep and possibly infinite".
It looks like limitation of TypeScript.
microsoft/TypeScript#34933 (comment)
from typed-inject.
Related Issues (20)
- Can't provide a class before its dependencies HOT 2
- Suggestion: Avoid adding source maps paths to published files HOT 6
- enhance needed: optional HOT 6
- Support TS 3.8 with full type safety
- Type instantiation is excessively deep and possibly infinite.ts(2589) HOT 6
- Support `as const` syntax for injection tokens
- Add a way to dispose all child injectors
- Async factories HOT 1
- Get the token of the target HOT 1
- Disposed children retained by parent HOT 2
- Difference between resolve and injectClass HOT 3
- Question: Circular Dependencies HOT 2
- Support for high order functions HOT 1
- Typescript improvments... :(
- Question: How to get an instance of a class only from its token?
- Use of mutation testing in typed-inject - Help needed
- Question: [typed-inject in Clean Architecture] How to inject instances so that other registered instances can reference them while being used as injectables themselves by other instances? HOT 1
- Question: IOC container in a react project HOT 4
- How to handle class inheritance with extra deps? HOT 4
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from typed-inject.