Skip to content

Commit

Permalink
Add generic parameter to AwilixContainer interface
Browse files Browse the repository at this point in the history
Remove unnecessary conversions

CR fix

Revert
  • Loading branch information
roikoren755 committed Feb 28, 2020
1 parent c1d3256 commit 4b69c64
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 30 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1335,10 +1335,10 @@ because they depend on Node-specific packages.
# Contributing
Clone repo, run `npm i` to install all dependencies, run `npm run build` to create an initial build, and then
`npm run test -- --watchAll` to start writing code.
Clone repo, run `yarn` to install all dependencies, run `yarn build` to create an initial build, and then
`yarn test --watchAll` to start writing code.
For code coverage, run `npm run cover`.
For code coverage, run `yarn cover`.
If you submit a PR, please aim for 100% code coverage and no linting errors.
Travis will fail if there are linting errors. Thank you for considering
Expand Down
9 changes: 7 additions & 2 deletions examples/typescript/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,13 @@ import { createContainer, asClass, InjectionMode } from '../../../src/awilix'
import TestService from './services/TestService'
import DependentService from './services/DependentService'

interface ICradle {
testService: TestService
depService: DependentService
}

// Create the container
const container = createContainer({
const container = createContainer<ICradle>({
injectionMode: InjectionMode.CLASSIC
})

Expand All @@ -15,7 +20,7 @@ container.register({
})

// Resolve a dependency using the cradle.
let dep1: DependentService = container.cradle.depService
let dep1 = container.cradle.depService
// Resolve a dependency using `resolve`
let dep2 = container.resolve<DependentService>('depService')

Expand Down
36 changes: 18 additions & 18 deletions src/container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { AwilixResolutionError, AwilixTypeError } from './errors'
* The container returned from createContainer has some methods and properties.
* @interface AwilixContainer
*/
export interface AwilixContainer {
export interface AwilixContainer<Cradle extends object = any> {
/**
* Options the container was configured with.
*/
Expand All @@ -30,7 +30,7 @@ export interface AwilixContainer {
* The proxy injected when using `PROXY` injection mode.
* Can be used as-is.
*/
readonly cradle: any
readonly cradle: Cradle
/**
* Getter for the rolled up registrations that merges the container family tree.
*/
Expand All @@ -42,7 +42,7 @@ export interface AwilixContainer {
/**
* Creates a scoped container with this one as the parent.
*/
createScope(): AwilixContainer
createScope<T extends object = any>(): AwilixContainer<Cradle & T>
/**
* Used by `util.inspect`.
*/
Expand All @@ -67,7 +67,7 @@ export interface AwilixContainer {
/**
* Pairs resolvers to registration names and registers them.
*/
register(nameAndRegistrationPair: NameAndRegistrationPair): this
register(nameAndRegistrationPair: NameAndRegistrationPair<Cradle>): this
/**
* Resolves the registration with the given name.
*
Expand Down Expand Up @@ -122,23 +122,23 @@ export interface ResolveOptions {
/**
* Cache entry.
*/
export interface CacheEntry {
export interface CacheEntry<T = any> {
/**
* The resolver that resolved the value.
*/
resolver: Resolver<any>
resolver: Resolver<T>
/**
* The resolved value.
*/
value: any
value: T
}

/**
* Register a Registration
* @interface NameAndRegistrationPair
*/
export interface NameAndRegistrationPair {
[key: string]: Resolver<any>
export type NameAndRegistrationPair<T> = {
[U in keyof T]?: Resolver<T[U]>
}

/**
Expand Down Expand Up @@ -194,10 +194,10 @@ const ROLL_UP_REGISTRATIONS = Symbol('rollUpRegistrations')
* @return {object}
* The container.
*/
export function createContainer(
export function createContainer<T extends object = any, U extends object = any>(
options?: ContainerOptions,
parentContainer?: AwilixContainer
): AwilixContainer {
parentContainer?: AwilixContainer<U>
): AwilixContainer<T> {
options = {
injectionMode: InjectionMode.PROXY,
...options
Expand All @@ -221,7 +221,7 @@ export function createContainer(
* knowing where they come from. I call it the "cradle" because
* it is where registered things come to life at resolution-time.
*/
const cradle: { [key: string]: any } = new Proxy(
const cradle = new Proxy(
{
[util.inspect.custom]: inspectCradle
},
Expand Down Expand Up @@ -274,12 +274,12 @@ export function createContainer(
return undefined
}
}
)
) as T

// The container being exposed.
const container = {
options,
cradle: cradle as any,
cradle,
inspect,
cache: new Map<string | symbol, CacheEntry>(),
loadModules,
Expand Down Expand Up @@ -360,14 +360,14 @@ export function createContainer(
* @return {object}
* The scoped container.
*/
function createScope(): AwilixContainer {
return createContainer(options, container)
function createScope<P extends object>(): AwilixContainer<P & T> {
return createContainer(options, container as AwilixContainer<T>)
}

/**
* Adds a registration for a resolver.
*/
function register(arg1: any, arg2: any): AwilixContainer {
function register(arg1: any, arg2: any): AwilixContainer<T> {
const obj = nameValueToObject(arg1, arg2)
const keys = [...Object.keys(obj), ...Object.getOwnPropertySymbols(obj)]

Expand Down
19 changes: 12 additions & 7 deletions src/resolvers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@ export const RESOLVER = Symbol('Awilix Resolver Config')
*
* @type {Function}
*/
export type InjectorFunction = (container: AwilixContainer) => object
export type InjectorFunction = <T extends object>(
container: AwilixContainer<T>
) => object

/**
* A resolver object returned by asClass(), asFunction() or asValue().
*/
export interface Resolver<T> extends ResolverOptions<T> {
resolve(container: AwilixContainer): T
resolve<U extends object>(container: AwilixContainer<U>): T
}

/**
Expand Down Expand Up @@ -335,7 +337,10 @@ function updateResolver<T, A extends Resolver<T>, B>(
* @param {Object} locals
* @return {Function}
*/
function wrapWithLocals(container: AwilixContainer, locals: any) {
function wrapWithLocals<T extends object>(
container: AwilixContainer<T>,
locals: any
) {
return function wrappedResolve(name: string, resolveOpts: ResolveOptions) {
if (name in locals) {
return locals[name]
Expand All @@ -353,8 +358,8 @@ function wrapWithLocals(container: AwilixContainer, locals: any) {
* @param {Function} injector
* @return {Proxy}
*/
function createInjectorProxy(
container: AwilixContainer,
function createInjectorProxy<T extends object>(
container: AwilixContainer<T>,
injector: InjectorFunction
) {
const locals = injector(container) as any
Expand Down Expand Up @@ -444,9 +449,9 @@ function generateResolve(fn: Function, dependencyParseTarget?: Function) {
const dependencies = parseDependencies(dependencyParseTarget)

// Use a regular function instead of an arrow function to facilitate binding to the resolver.
return function resolve(
return function resolve<T extends object>(
this: BuildResolver<any>,
container: AwilixContainer
container: AwilixContainer<T>
) {
// Because the container holds a global reolutionMode we need to determine it in the proper order of precedence:
// resolver -> container -> default value
Expand Down

0 comments on commit 4b69c64

Please sign in to comment.