Skip to content

Commit

Permalink
Fix published provideClass return type inference. (#14)
Browse files Browse the repository at this point in the history
Without the type assertion, compiler resulting npm package type
definition for `provideClass` looks like:
```
providesClass: <Token extends TokenType, Service, Tokens extends readonly ValidTokens<Services>[]>(token: Token, cls: InjectableClass<Services, Service, Tokens>) => Container<AddService<Services, Token, import("./Injectable").ConstructorReturnType<InjectableClass<Services, Service, Tokens>>>>;
```

The last bit (`ConstructorReturnType<InjectableClass<Services, Service,
Tokens>>>>`) is somehow problematic. Resolving types for services
provided using the function breaks, e.g.
`container.providesClass('serivice', Service)` returns a container of
type `Container<{ service: any }>`.

The fix addresses the issue by asserting the function's return type, so
the generated function signature looks like:

```
providesClass: <Token extends TokenType, Service, Tokens extends readonly ValidTokens<Services>[]>(token: Token, cls: InjectableClass<Services, Service, Tokens>) => Container<AddService<Services, Token, Service>>;
```
With that `container.providesClass('serivice', Service)` correctly
returns a container of type `Container<{ service: Service }>`.
  • Loading branch information
kburov-sc authored Nov 28, 2024
1 parent 44b4588 commit 5b2c728
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 7 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@snap/ts-inject",
"version": "0.3.1",
"version": "0.3.2",
"description": "100% typesafe dependency injection framework for TypeScript projects",
"license": "MIT",
"author": "Snap Inc.",
Expand Down
15 changes: 9 additions & 6 deletions src/Container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,8 @@ export class Container<Services = {}> {
providesClass = <Token extends TokenType, Service, Tokens extends readonly ValidTokens<Services>[]>(
token: Token,
cls: InjectableClass<Services, Service, Tokens>
) => this.providesService(ClassInjectable(token, cls));
): Container<AddService<Services, Token, Service>> =>
this.providesService(ClassInjectable(token, cls)) as Container<AddService<Services, Token, Service>>;

/**
* Registers a static value as a service in the container. This method is ideal for services that do not
Expand All @@ -433,8 +434,10 @@ export class Container<Services = {}> {
* @returns A new Container instance that includes the provided service, allowing for chaining additional
* `provides` calls.
*/
providesValue = <Token extends TokenType, Service>(token: Token, value: Service) =>
this.providesService(Injectable(token, [], () => value));
providesValue = <Token extends TokenType, Service>(
token: Token,
value: Service
): Container<AddService<Services, Token, Service>> => this.providesService(Injectable(token, [], () => value));

/**
* Appends a value to the array associated with a specified token in the current Container, then returns
Expand All @@ -455,7 +458,7 @@ export class Container<Services = {}> {
appendValue = <Token extends keyof Services, Service extends ArrayElement<Services[Token]>>(
token: Token,
value: Service
) => this.providesService(ConcatInjectable(token, () => value)) as Container<Services>;
): Container<Services> => this.providesService(ConcatInjectable(token, () => value)) as Container<Services>;

/**
* Appends an injectable class factory to the array associated with a specified token in the current Container,
Expand All @@ -479,7 +482,7 @@ export class Container<Services = {}> {
>(
token: Token,
cls: InjectableClass<Services, Service, Tokens>
) =>
): Container<Services> =>
this.providesService(
ConcatInjectable(token, () => this.providesClass(token, cls).get(token))
) as Container<Services>;
Expand Down Expand Up @@ -507,7 +510,7 @@ export class Container<Services = {}> {
Service extends ArrayElement<Services[Token]>,
>(
fn: InjectableFunction<Services, Tokens, Token, Service>
) =>
): Container<Services> =>
this.providesService(
ConcatInjectable(fn.token, () => this.providesService(fn).get(fn.token))
) as Container<Services>;
Expand Down

0 comments on commit 5b2c728

Please sign in to comment.