thiagobustamante / typescript-ioc

A Lightweight annotation-based dependency injection container for typescript.
MIT License
526 stars 64 forks source link

Add stronger typing to Container.get() via usage of generics #47

Closed ccl2of4 closed 5 years ago

ccl2of4 commented 5 years ago

First, thanks for your work on this library. I've been using it extensively for over a year now :smile:

Motivation

The current Container.get() returns any, which means you need an explicit type annotation or cast afterward in order to get any type safety.

By using generics, we can make the typescript compiler a little smarter - it can assume that the type you get out of Container.get() is the same type you pass to it.

// old
const foo = Container.get(Foo); // Inferred type of `foo` is `any`.
const foo: Foo = Container.get(Foo); // Explicit type annotation makes type `foo`.
const foo = Container.get(Foo) as Foo; // Explicit cast make type `foo`.

// new
const foo = Container.get(Foo); // Inferred type of `foo` is `Foo`, no need for type annotations or casting.

The new function signature

I originally tried to use new(...args: Array<any>): T, but this doesn't work for abstract classes because abstract constructors don't match that type signature.

So, after seeing https://stackoverflow.com/questions/36886082/abstract-constructor-type-in-typescript#38642922, it looks like the type Function & {prototype: T} encompasses both concrete and abstract classes and should cover all use cases

coveralls commented 5 years ago

Coverage Status

Coverage remained the same at 91.353% when pulling 2b4ec2ff3d758b65696b7208e5313526769541cd on ccl2of4:stronger-typing into ab4e827d1b4cd3a1cb4293aa11b5a5586c3bda6e on thiagobustamante:master.