diff --git a/README.md b/README.md index 25bae9b..6de9282 100644 --- a/README.md +++ b/README.md @@ -216,6 +216,38 @@ const injector = new Injector([ ``` +### Type Service Retrival + +[`didi`](https://github.com/nikku/didi) ships type declarations that allow you to use it in a type safe manner. + +#### Explicit Typing + +Pass a type attribute to `Injector#get` to retrieve a service as a known type: + +```typescript +const hifiComponent = injector.get('hifiComponent'); + +// typed as +hifiComponent.toggle(); +``` + +#### Implicit Typing + +Configure the `Injector` through a service map and automatically cast services +to known types: + +```typescript +type ServiceMap = { + 'hifiComponent': HifiComponent +}; + +const injector = new Injector(...); + +const hifiComponent = injector.get('hifiComponent'); +// typed as +``` + + ## Credits This library builds on top of the (now unmaintained) [node-di][node-di] library. `didi` is a maintained fork that adds support for ES6, the minification safe array notation, and other features. diff --git a/lib/index.d.ts b/lib/index.d.ts index 04ccf1c..f5cdc30 100644 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -71,13 +71,21 @@ export type LocalsMap = { export type ModuleDefinition = ModuleDeclaration; -export class Injector { + +export class Injector< + ServiceMap = null +> { /** * Create an injector from a set of modules. */ constructor(modules: ModuleDefinition[], parent?: InjectorContext); + /** + * Return a named service, looked up from the existing service map. + */ + get(name: Name): ServiceMap[Name]; + /** * Return a named service, and throws if it is not found. */ diff --git a/test/integration/ts.spec.ts b/test/integration/ts.spec.ts index 00b00d6..1fd52a3 100644 --- a/test/integration/ts.spec.ts +++ b/test/integration/ts.spec.ts @@ -59,6 +59,39 @@ describe('typed', function() { expect(injector).to.exist; }); + + it('should offer typed injections', function() { + + // given + type ServiceMap = { + 'foo': 1, + 'bar': 'BAR' + }; + + // when + const injector = new Injector([ + { + foo: [ 'value', 1 ], + bar: [ 'value', 'BAR' ] + } + ]); + + // then + const foo = injector.get('foo'); + expect(foo).to.eql(1); + + const bar = injector.get('bar'); + expect(bar).to.eql('BAR'); + + const baz = injector.get('baz', false); + expect(baz).not.to.exist; + + // illegal usage, but if you think you know better + // we still accept it + const boolBar = injector.get('bar'); + expect(boolBar).to.exist; + }); + });