Skip to content

Commit

Permalink
fix: types for multiple tokens
Browse files Browse the repository at this point in the history
  • Loading branch information
exuanbo committed Oct 10, 2024
1 parent 2373134 commit 39fb5e3
Show file tree
Hide file tree
Showing 7 changed files with 33 additions and 18 deletions.
6 changes: 3 additions & 3 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import type {Resolvable} from './resolvable'
import type {InjectionScope} from './scope'
import type {InjectionToken} from './token'

export interface InjectionConfig<T> {
export interface InjectionConfig<T extends any[]> {
scope?: InjectionScope
tokens: InjectionToken<T>[]
tokens: {[K in keyof T]: InjectionToken<T[K]>}
}

/** @internal */
export function isConfigLike<T>(resolvable: Resolvable<T>) {
export function isConfig<T>(resolvable: Resolvable<T>) {
return 'tokens' in resolvable
}
11 changes: 7 additions & 4 deletions src/container.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {isConfigLike} from './config'
import {type InjectionConfig, isConfig} from './config'
import {createContext} from './create-context'
import {assert, ErrorMessage, expectNever} from './errors'
import {getMetadata} from './metadata'
Expand Down Expand Up @@ -59,7 +59,7 @@ export class Container {
if (isConstructor(providable)) {
const Class = providable
const metadata = getMetadata(Class)
const tokens = metadata?.tokens || [Class]
const tokens = (metadata?.tokens || []).concat(Class)
tokens.forEach((token) => {
const provider = {
token,
Expand All @@ -76,8 +76,11 @@ export class Container {
}
}

resolve = <T>(resolvable: Resolvable<T>): T => {
if (isConfigLike(resolvable)) {
resolve<T extends any[]>(config: InjectionConfig<T>): T[number]
resolve<T>(token: InjectionToken<T>): T
resolve<T>(resolvable: Resolvable<T>): T
resolve<T>(resolvable: Resolvable<T>): T {
if (isConfig(resolvable)) {
const config = resolvable
const tokens = config.tokens
for (const token of tokens) {
Expand Down
23 changes: 15 additions & 8 deletions src/decorators.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,42 @@
import type {InjectionConfig} from './config'
import {inject} from './inject'
import {metadataRegistry} from './metadata'
import type {Resolvable} from './resolvable'
import type {InjectionScope} from './scope'
import type {Constructor, InjectionToken} from './token'

export type ClassDecorator<Class extends Constructor<object>> = (
export type ClassDecorator<Class extends Constructor> = (
value: Class,
context: ClassDecoratorContext<Class>,
) => Class | void

export type ClassFieldDecorator<Value> = <This extends object>(
export type ClassFieldDecorator<Value> = <This>(
value: undefined,
context: ClassFieldDecoratorContext<This, Value>,
) => ClassFieldInitializer<This, Value> | void

export type ClassFieldInitializer<This extends object, Value> = (
export type ClassFieldInitializer<This, Value> = (
this: This,
initialValue: Value,
) => Value

export function Injectable<T extends object>(...tokens: InjectionToken<T>[]): ClassDecorator<Constructor<T>> {
export function Injectable<T>(...tokens: InjectionToken<T>[]): ClassDecorator<Constructor<T>> {
return (_value, context) => {
const metadata = metadataRegistry.ensure(context.metadata)
const metadata = metadataRegistry.ensure<T>(context.metadata)
metadata.tokens.push(...tokens)
}
}

export function Scoped<T extends object>(scope: InjectionScope): ClassDecorator<Constructor<T>> {
export function Scoped<T>(scope: InjectionScope): ClassDecorator<Constructor<T>> {
return (_value, context) => {
const metadata = metadataRegistry.ensure(context.metadata)
const metadata = metadataRegistry.ensure<T>(context.metadata)
metadata.scope = scope
}
}

export function Inject<T extends any[]>(config: InjectionConfig<T>): ClassFieldDecorator<T[number]>
export function Inject<T>(token: InjectionToken<T>): ClassFieldDecorator<T>
export function Inject<T>(resolvable: Resolvable<T>): ClassFieldDecorator<T>
export function Inject<T>(resolvable: Resolvable<T>): ClassFieldDecorator<T> {
return (_value, _context) => {
return (_initialValue) => {
Expand All @@ -41,9 +45,12 @@ export function Inject<T>(resolvable: Resolvable<T>): ClassFieldDecorator<T> {
}
}

export function Deferred<T extends any[]>(config: InjectionConfig<T>): ClassFieldDecorator<T[number]>
export function Deferred<T>(token: InjectionToken<T>): ClassFieldDecorator<T>
export function Deferred<T>(resolvable: Resolvable<T>): ClassFieldDecorator<T>
export function Deferred<T>(resolvable: Resolvable<T>): ClassFieldDecorator<T> {
return (_value, context) => {
const metadata = metadataRegistry.ensure(context.metadata)
const metadata = metadataRegistry.ensure<T>(context.metadata)
metadata.dependencies.add({
resolvable,
setValue: context.access.set,
Expand Down
5 changes: 5 additions & 0 deletions src/inject.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import type {InjectionConfig} from './config'
import {useContainer} from './container'
import {assert, ErrorMessage} from './errors'
import type {Resolvable} from './resolvable'
import type {InjectionToken} from './token'

export function inject<T extends any[]>(config: InjectionConfig<T>): T[number]
export function inject<T>(token: InjectionToken<T>): T
export function inject<T>(resolvable: Resolvable<T>): T
export function inject<T>(resolvable: Resolvable<T>): T {
const container = useContainer()
assert(container, ErrorMessage.InjectOutsideOfContext)
Expand Down
2 changes: 1 addition & 1 deletion src/metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type {InjectionConfig} from './config'
import type {Resolvable} from './resolvable'
import type {Constructor} from './token'

export interface InjectionMetadata<T = any> extends InjectionConfig<T> {
export interface InjectionMetadata<T = any> extends InjectionConfig<T[]> {
dependencies: Set<InjectionDependency>
}

Expand Down
2 changes: 1 addition & 1 deletion src/resolvable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ import type {InjectionToken} from './token'

export type Resolvable<T> =
| InjectionToken<T>
| InjectionConfig<T>
| InjectionConfig<T[]>
2 changes: 1 addition & 1 deletion src/token.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export type InjectionToken<T = any> = Constructor<T> | Type<T>

export interface Constructor<T> {
export interface Constructor<T = any> {
new (...args: []): T
}

Expand Down

0 comments on commit 39fb5e3

Please sign in to comment.