# tslint-circular-dependencies

> This package contains four rules, including fixes, to work around some of the issues that arise with circular imports:

Latest version **0.1.0** (published 2017-09-11) · MIT license · 0 weekly downloads

> **Deprecated.** This package is deprecated.

## Install

```sh
npm install tslint-circular-dependencies
pnpm add tslint-circular-dependencies
yarn add tslint-circular-dependencies
bun add tslint-circular-dependencies
```

## Health

**Score 10/100 (F)** — status: deprecated.

Negative: deprecated.

## Facts

| | |
|---|---|
| Version | 0.1.0 |
| Published | 2017-09-11 |
| First published | 2017-07-14 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | none |
| Module format | CommonJS |
| Dependencies | 7 |
| Known vulnerabilities | 0 |
| Install scripts | yes |
| Author | Andreas Pizsa |
| Maintainers | andreaspizsa |

## Links

- npm: https://www.npmjs.com/package/tslint-circular-dependencies
- Repository: https://github.com/GoodgameStudios/tslint-circular-dependencies
- Homepage: https://github.com/GoodgameStudios/tslint-circular-dependencies#readme
- Issues: https://github.com/GoodgameStudios/tslint-circular-dependencies/issues
- npm.io page: https://npm.io/package/tslint-circular-dependencies

## Dependencies (7)

- [debug](https://npm.io/package/debug.md) ^2.6.8
- [lodash](https://npm.io/package/lodash.md) ^4.17.4
- [tslint](https://npm.io/package/tslint.md) ^5.5.0
- [typescript](https://npm.io/package/typescript.md) ^2.4.1
- [@types/node](https://npm.io/package/@types/node.md) ^8.0.14
- [read-pkg-up](https://npm.io/package/read-pkg-up.md) ^2.0.0
- [@types/lodash](https://npm.io/package/@types/lodash.md) ^4.14.68

## Recent versions

- 0.1.0 (latest) — 2017-09-11
- 0.0.14 — 2017-09-11
- 0.0.13 — 2017-07-27
- 0.0.12 — 2017-07-19
- 0.0.11 — 2017-07-19
- 0.0.10 — 2017-07-17
- 0.0.9 — 2017-07-17
- 0.0.8 — 2017-07-17
- 0.0.7 — 2017-07-17
- 0.0.6 — 2017-07-17
- 0.0.5 — 2017-07-14
- 0.0.4 — 2017-07-14
- 0.0.3 — 2017-07-14
- 0.0.2 — 2017-07-14
- 0.0.1 — 2017-07-14

## README

# `tslint` rules to work around circular dependencies

This package contains four rules, including fixes, to work around some of the issues
that arise with circular imports:

+ `imports-after-export`
+ `initialize-statics-after-imports`
+ `new-instance-after-imports`
+ `no-instanceof-operator`

## Usage

#### Install

```
npm install -D tslint-circular-dependencies
```

This will install the rules and set up your `tslint.json` file.

> **TypeScript 2.4.1**
> These rules have been tested with TypeScript 2.4.1. If you're seeing _no output_ when you run these rules, try updating TypeScript to this version.

#### Run

```
tslint [path] --fix
```

#### Manually configuring `tslint.json` (optional)

This package will install itself into your `tslint.json` as follows:

```
  "extends" : [
    ...
    "tslint-circular-dependencies"
    ...
  ]
```

> **Keep the rule names intact**. `tslint` does not document a certain execution order for rules, but right now they are executed in alphabetic order. It is important that the rules in this package are executed in a particular order, and thats 1. `imports-after-export`, 2. `initialize-statics-after-imports`, 3. `new-instance-after-imports`.


# Inside the Rules
### `imports-after-export`
Moves all `import` statements – except those that are used as superclasses in an `extends` clause – _after_ the last `export` statement.

#### Why
Circular `import`s work if the `import` occurs after `export`.

The following code **will fail**:

```
// a.ts
import { B } from './b';

export class A {
  constructor() {
    this.b = new B();
  }
}
```
```
// b.ts
import { A } from './a';

export class B {
  constructor() {
    this.a = new A();
  }
}
```

This fails because at the time the `import` is executed, `module.exports` is still `undefined`.

| Step| Statement                  | a.exports   | b.exports   |
|----:|----------------------------|-------------|-------------|
| *1* | `import { B } from './b';` | `undefined` | `undefined` |
| *2* | `import { A } from './a';` | `undefined` | `undefined` |
| *3* | `export class B {...}`     | `undefined` | `class B`   |
| *4* | `export class A {...}`     | `class A`   | `class B`   |

The following code **will work**:

```
// a.ts
export class A {
  constructor() {
    this.b = new B();
  }
}

import { B } from './b';

```
```
// b.ts
export class B {
  constructor() {
    this.a = new A();
  }
}

import { A } from './a';
```

| Step| statement                  | a.exports   | b.exports   |
|----:|----------------------------|-------------|-------------|
| *1* | `export class A {...}`     | `class A`   | `undefined` |
| *2* | `import { B } from './b';` | `class A`   | `undefined` |
| *3* | `export class B {...}`     | `class A`   | `class B`   |
| *4* | `import { A } from './a';` | `class A`   | `class B`   |


### `initialize-statics-after-imports`
This rule
* encapsulates non-primitive `static` initializers in a `static` `function`
* executes that `static` `function` after all `import` statements

#### Improvement Suggestion

* **Only move initializers that reference imported symbols**. This rule currently encapsulates all `static` initializers into a function. This could be more accurately move only those `static` initializers that reference `import`ed symbols. Keep in mind this may mean you'd have to analyze the execution path in case of initializers like this:

```
class A {
  public static x = A.initializeX();

  private static initializeX() {
    return new X(); // this will fail because X isn't imported yet
  }
}

import { X } from 'X';
```

### `new-instance-after-imports`
This rule moves `new` expressions to _after_ the last `import` statement to make sure all dependencies have been loaded.


```
class A {
  ...
}

new A(); // will be moved to after `import` statement

import { B } from 'B';

```


### `no-instanceof-operator`

This rule changes any use of the `instanceof` operator with a `constructor.name` comparison, e.g.

Original code **before** this rule:

```
class A {}
let a = new A();
a instanceof A;
```

Original code **after** this rule:

```
class A {}
let a = new A();
a.constructor.name === 'A';
```

# Related Projects

[tslint-no-circular-imports](https://github.com/bcherny/tslint-no-circular-imports/) - TSLint plugin to detect and warn about circular imports

[dependency-cruiser](https://www.npmjs.com/package/dependency-cruiser) – Validate and visualize dependencies. With your rules. JavaScript. TypeScript. CoffeeScript. ES6, CommonJS, AMD.

---
_Source: https://npm.io/package/tslint-circular-dependencies · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
