# Cannot autoinject abstract classes in aurelia-dependency-injection 1.5.0

**URL:** <https://discourse.aurelia.io/t/cannot-autoinject-abstract-classes-in-aurelia-dependency-injection-1-5-0/2844>\
**Category:** Help Requests\
**Created:** [August 19, 2019, 10:30am UTC](https://discourse.aurelia.io/t/cannot-autoinject-abstract-classes-in-aurelia-dependency-injection-1-5-0/2844 "2019-08-19T10:30:19Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![m-gallesio](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/m-gallesio/32/1288_2.png) [@m-gallesio](https://discourse.aurelia.io/u/m-gallesio)\
**Post date:** [August 19, 2019, 10:30am UTC](https://discourse.aurelia.io/t/cannot-autoinject-abstract-classes-in-aurelia-dependency-injection-1-5-0/2844/1 "2019-08-19T10:30:19Z")

</div>

A [recent update](https://github.com/aurelia/dependency-injection/releases/tag/1.5.0) to the dependency injection makes the `autoinject` (and i guess others) decorator incompatible with TypeScript abstract classes.  
This breaks an inheritance-based scenario common in our application:

- we use abstract, generic classes for viewModels with high-level shared functionality (e.g. a generic form control, a generic detail page…). These use `@autoinject` and have a defined constructor with a sometimes large number of arguments: for reference the generic detail page constructor currently has 9 arguments, all services (Aurelia’s or ours) like EventAggregator, Router and BindingSignaler
- the concrete viewModels inherit (`extends`) from these abstract base viewModels. Most of the time there is no need to override the default constructor as it covers everything, so the concrete viewModel has no explicitly defined constructor and no `@autoinject`.

We have currently downgraded to 1.4.2 (and aurelia-validation to 1.4.0), but this is obviously not a long-term solution.

To fix this problem in our application, we could:

- make the abstract classes not abstract. This would cause no concrete issues but defeats the semantic purpose of using abstract in the first place.
- move `@autoinject` to the last level of concrete classes. This is arguably more semantically correct, but most of the time it would be redundant and prone to being forgotten (in the transition stage, at least).

However, before rushing to change such a large number of files I would appreciate to know if our structure is sound enough, and if so if it is enough of a common / useful use case to warrant some kind of consideration in the aurelia-dependency-injection type definitions.

If this is relevant, we currently have to target ES5.

* * *

Furthermore, with 1.5.0 we get this error while compiling:`
…/node_modules/aurelia-dependency-injection/dist/aurelia-dependency-injection.d.ts(139,162): error TS2536: Type ‘number’ cannot be used to index type ‘TArgs’.
`This could be related to our version of TypeScript, however (I am decently sure it is 3.1 which is quite outdated).

---

<div class="post-metadata">

**Author:** ![davismj](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/davismj/32/267_2.png) [@davismj](https://discourse.aurelia.io/u/davismj)\
**Post date:** [August 19, 2019, 1:22pm UTC](https://discourse.aurelia.io/t/cannot-autoinject-abstract-classes-in-aurelia-dependency-injection-1-5-0/2844/2 "2019-08-19T13:22:09Z")

</div>

For cases like these I tend to not depend on @autoinject but instead manually @inject. Is that an option?

---

<div class="post-metadata">

**Author:** ![fkleuver](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/fkleuver/32/994_2.png) [@fkleuver](https://discourse.aurelia.io/u/fkleuver)\
**Post date:** [August 19, 2019, 1:39pm UTC](https://discourse.aurelia.io/t/cannot-autoinject-abstract-classes-in-aurelia-dependency-injection-1-5-0/2844/3 "2019-08-19T13:39:57Z")

</div>

Looks like an oversight in that change. The constraint `(new() => any)` was added in order to limit the decorator to `new`able types, but abstract classes are not `new`able.

We may need to loosen up the type constraints again. See [https://github.com/aurelia/dependency-injection/pull/182](https://github.com/aurelia/dependency-injection/pull/182)

---

<div class="post-metadata">

**Author:** ![m-gallesio](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/m-gallesio/32/1288_2.png) [@m-gallesio](https://discourse.aurelia.io/u/m-gallesio)\
**Post date:** [August 19, 2019, 3:38pm UTC](https://discourse.aurelia.io/t/cannot-autoinject-abstract-classes-in-aurelia-dependency-injection-1-5-0/2844/4 "2019-08-19T15:38:24Z")

</div>

It could be, though we’d lose the terseness of `@autoinject` which has always served us well.  
Does `@inject` have any relevant advantages over `@autoinject`? Note that we currently do not directly use more complex DI feature like NewInstance.of.

---

<div class="post-metadata">

**Author:** ![DrSammyD](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/drsammyd/32/1602_2.png) [@DrSammyD](https://discourse.aurelia.io/u/DrSammyD)\
**Post date:** [August 21, 2019, 10:28pm UTC](https://discourse.aurelia.io/t/cannot-autoinject-abstract-classes-in-aurelia-dependency-injection-1-5-0/2844/5 "2019-08-21T22:28:29Z")

</div>

@m-gallesio I verified @autoinject works at typescript@3.4.1

---

<div class="post-metadata">

**Author:** ![m-gallesio](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/m-gallesio/32/1288_2.png) [@m-gallesio](https://discourse.aurelia.io/u/m-gallesio)\
**Post date:** [August 23, 2019, 6:56am UTC](https://discourse.aurelia.io/t/cannot-autoinject-abstract-classes-in-aurelia-dependency-injection-1-5-0/2844/6 "2019-08-23T06:56:33Z")

</div>

Thank you for your feedback, I will check whenever possible (our project at the moment has higher-priority issues).

---

<div class="post-metadata">

**Author:** ![m-gallesio](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/m-gallesio/32/1288_2.png) [@m-gallesio](https://discourse.aurelia.io/u/m-gallesio)\
**Post date:** [August 23, 2019, 12:30pm UTC](https://discourse.aurelia.io/t/cannot-autoinject-abstract-classes-in-aurelia-dependency-injection-1-5-0/2844/7 "2019-08-23T12:30:02Z")

</div>

Unfortunately it still does not seem to work, even with later TypeScript version (I have tried installing 3.5.2).

Here is a minimal project (created with Visual Studio 2017’s node.js application template) which should reproduce the issue:

_package.json:_

```
{
  "name": "tstest",
  "version": "0.0.0",
  "description": "TSTest",
  "main": "app.js",
  "author": {
    "name": ""
  },
  "devDependencies": {
    "@types/node": "^8.0.14"
  },
  "dependencies": {
    "aurelia-dependency-injection": "^1.5.0",
    "aurelia-framework": "^1.3.1",
    "aurelia-validation": "^1.5.0"
  }
}

```

_tsconfig.json:_

```
{
  "compilerOptions": {
    "module": "commonjs",
    "target": "es5",
    "lib": ["es6"],
    "sourceMap": true,
    "experimentalDecorators": true
  },
  "exclude": [
    "node_modules"
  ]
}

```

_app.ts:_

```
import { autoinject } from "aurelia-framework"
@autoinject
export abstract class Test {
}

```

No matter what, the TypeScript compiler complains with:

```
error TS2345: Argument of type 'typeof Test' is not assignable to parameter of type 'DependencyCtor<any, any, any>'.
Cannot assign an abstract constructor type to a non-abstract constructor type.
```

---

<div class="post-metadata">

**Author:** ![m-gallesio](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/m-gallesio/32/1288_2.png) [@m-gallesio](https://discourse.aurelia.io/u/m-gallesio)\
**Post date:** [April 5, 2021, 9:27am UTC](https://discourse.aurelia.io/t/cannot-autoinject-abstract-classes-in-aurelia-dependency-injection-1-5-0/2844/8 "2021-04-05T09:27:11Z")

</div>

This is happening again in the current version of Aurelia 2 (2.0.0-alpha.2).  
From what I understand `autoinject` has been conflated with `inject`.

This:

```auto
@inject()
export abstract class IndexPage<TItem> implements IRouteViewModel {
}

```

fails with the following error:

```auto
Argument of type 'typeof IndexPage' is not assignable to parameter of type 'Injectable<{}>'.
  Type 'typeof IndexPage' is not assignable to type 'Constructable<{}>'.
    Cannot assign an abstract constructor type to a non-abstract constructor type.ts(2345)

```

I seem to recall some recent version of Typescript doing (or planning to do) something with abstract constructors; it might be worth looking into.

---

<div class="post-metadata">

**Author:** ![bigopon](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/bigopon/32/18_2.png) [@bigopon](https://discourse.aurelia.io/u/bigopon)\
**Post date:** [April 6, 2021, 2:19am UTC](https://discourse.aurelia.io/t/cannot-autoinject-abstract-classes-in-aurelia-dependency-injection-1-5-0/2844/9 "2021-04-06T02:19:12Z")

</div>

Ahh interesting, well maybe we will loosen it in v2 like we did in v1 👍

---

<div class="post-metadata">

**Author:** ![DrSammyD](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/drsammyd/32/1602_2.png) [@DrSammyD](https://discourse.aurelia.io/u/DrSammyD)\
**Post date:** [May 26, 2022, 3:30am UTC](https://discourse.aurelia.io/t/cannot-autoinject-abstract-classes-in-aurelia-dependency-injection-1-5-0/2844/10 "2022-05-26T03:30:49Z")

</div>

They enabled Abstract class argument inference.

```nohighlight
export type AbsCtorArgs<TBase> = TBase extends abstract new (...args: infer TArgs) => infer Impl ? TArgs : never;

```
