{"id":21155833,"url":"https://github.com/angular-extensions/lint-rules","last_synced_at":"2025-09-04T13:33:21.837Z","repository":{"id":40272531,"uuid":"241658725","full_name":"angular-extensions/lint-rules","owner":"angular-extensions","description":"tslint rules useful for angular projects","archived":false,"fork":false,"pushed_at":"2024-06-27T22:00:11.000Z","size":351,"stargazers_count":39,"open_issues_count":3,"forks_count":4,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-12-23T23:10:44.383Z","etag":null,"topics":["angular","hacktoberfest","lint","memory-leaks"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/angular-extensions.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-02-19T16:01:27.000Z","updated_at":"2023-12-20T05:31:47.000Z","dependencies_parsed_at":"2024-11-20T12:07:03.736Z","dependency_job_id":null,"html_url":"https://github.com/angular-extensions/lint-rules","commit_stats":{"total_commits":29,"total_committers":5,"mean_commits":5.8,"dds":0.4482758620689655,"last_synced_commit":"36e3596cf99f26fc8ed6d074bb095e92a3811c74"},"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/angular-extensions%2Flint-rules","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/angular-extensions%2Flint-rules/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/angular-extensions%2Flint-rules/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/angular-extensions%2Flint-rules/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/angular-extensions","download_url":"https://codeload.github.com/angular-extensions/lint-rules/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":231965490,"owners_count":18453091,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["angular","hacktoberfest","lint","memory-leaks"],"created_at":"2024-11-20T11:30:01.172Z","updated_at":"2024-12-31T09:13:53.084Z","avatar_url":"https://github.com/angular-extensions.png","language":"TypeScript","readme":"# @angular-extensions/lint-rules\n[https://github.com/angular-extensions/lint-rules](https://github.com/angular-extensions/lint-rules)\n\n[![npm version](https://img.shields.io/npm/v/@angular-extensions/lint-rules.svg?style=flat-square)](https://www.npmjs.com/package/@angular-extensions/lint-rules)\n[![npm downloads total](https://img.shields.io/npm/dt/@angular-extensions/lint-rules.svg?style=flat-square)](https://www.npmjs.com/package/@angular-extensions/lint-rules)\n[![npm downloads monthly](https://img.shields.io/npm/dm/@angular-extensions/lint-rules.svg?style=flat-square)](https://www.npmjs.com/package/@angular-extensions/lint-rules)\n[![CircleCI](https://circleci.com/gh/angular-extensions/lint-rules.svg?style=svg)](https://circleci.com/gh/angular-extensions/lint-rules)\n\n## Description\nThis repository offers some [tslint](https://github.com/palantir/tslint) rules useful for angular projects, see [Rules](#Rules).\n\n## Installation / Usage\n* Install the [@angular-extensions/lint-rules](https://www.npmjs.com/package/@angular-extensions/lint-rules) npm package:\n  ```\n  npm install @angular-extensions/lint-rules --save-dev\n  ```\n* Add `@angular-extensions/lint-rules` to the `extensions` list in your `tslint.json`:\n  ```json\n  {\n    \"extends\": [\n      \"tslint:recommended\",\n      \"@angular-extensions/lint-rules\"\n    ]\n  }\n  ```\n* Lint your project with\n  ```\n  ng lint\n  ```\n\n## Rules\nThe package includes the following rules:\n\n| Rule | Description | Details | Enabled by default? |\n| --- | --- | --- | --- |\n| `angular-call-super-lifecycle-method-in-extended-class` | Enforces the application to call parent lifecycle function e.g. `super.ngOnDestroy()` when using inheritance within an Angular component or directive. | [Details](#angular-call-super-lifecycle-method-in-extended-class) | yes |\n| `angular-rxjs-takeuntil-before-subscribe` | Enforces the application of the `takeUntil` operator when calling of `subscribe` within an Angular component or directive. | [Details](#angular-rxjs-takeuntil-before-subscribe) | yes |\n\n### angular-call-super-lifecycle-method-in-extended-class\nThis rule tries to avoid memory leaks and other problems in angular components and directives by ensuring that \na [life-cycle method](https://angular.io/guide/lifecycle-hooks), e.g. `ngOnDestroy(){}`, overriding its parent implementation \nmust call the parent implementation with `super.ngOnDestroy()`.\n\n#### Example\nThis should trigger an error:\n```typescript\nclass MyClass {\n    ngOnDestroy() {\n        const a = 5;\n    }\n}\n@Component({\n  selector: 'app-my'\n})\nclass MyComponent2 extends MyClass {\n\n    ngOnDestroy() {\n    ~~~~~~~~~~~            call to super.ngOnDestroy() is missing\n        const b = 6;\n    }\n}\n```\nwhile this should be fine:\n```typescript\nclass MyClass {\n    ngOnDestroy() {\n        const a = 5;\n    }\n}\n@Component({\n  selector: 'app-my'\n})\nclass MyComponent extends MyClass {\n\n    ngOnDestroy() {\n        super.ngOnDestroy();\n        const b = 6;\n    }\n}\n\n@Component({\n  selector: 'app-my2'\n})\nclass MyComponent2 {\n    ngOnDestroy() {\n        const b = 6;\n    }\n}\n```\n\n\n### angular-rxjs-takeuntil-before-subscribe\n\nThis rule tries to avoid memory leaks in angular components and directives when calling `.subscribe()` without properly unsubscribing \nby enforcing the application of the `takeUntil(this.destroy$)` operator before the `.subscribe()` \nas well as before certain operators (`shareReplay` without `refCount: true`)\nand ensuring the component implements the `ngOnDestroy` \nmethod invoking `this.destroy$.next()`.\nAll classes with a `@Component` or `@Directive` decorator and all their parent classes will be checked.\n\n#### Example\nThis should trigger an error:\n```typescript\n@Component({\n  selector: 'app-my',\n  template: '\u003cdiv\u003e{{k$ | async}}\u003c/div\u003e'\n})\nclass MyComponent {\n      ~~~~~~~~~~~    component containing subscribe must implement the ngOnDestroy() method\n\n    \n    k$ = a.pipe(shareReplay(1));\n                ~~~~~~~~~~~~~~   the shareReplay operator used within a component must be preceded by takeUntil\n\n    someMethod() {\n        const e = a.pipe(switchMap(_ =\u003e b)).subscribe();\n                                            ~~~~~~~~~      subscribe within a component must be preceded by takeUntil\n    }\n}\n```\n\nwhile this should be fine:\n```typescript\n@Component({\n  selector: 'app-my',\n  template: '\u003cdiv\u003e{{k$ | async}}\u003c/div\u003e'\n})\nclass MyComponent implements SomeInterface, OnDestroy {\n    private destroy$: Subject\u003cvoid\u003e = new Subject\u003cvoid\u003e();\n\n    k$ = a.pipe(takeUntil(this.destroy$), shareReplay(1));\n\n    someMethod() {\n        const e = a.pipe(switchMap(_ =\u003e b), takeUntil(this.destroy$)).subscribe();\n    }\n\n    ngOnDestroy() {\n      this.destroy$.next();\n    }\n}\n```\n\n\n## Further reading\n* https://slides.com/estebangehring/angular-app-memory-leak\n* https://blog.angularindepth.com/the-best-way-to-unsubscribe-rxjs-observable-in-the-angular-applications-d8f9aa42f6a0\n* https://github.com/cartant/rxjs-tslint-rules/pull/107\n\n## Contributors\n* Esteban Gehring ([@macjohnny](https://github.com/macjohnny))\n* Lutz Bliska ([@lbliska](https://github.com/lbliska))\n* Kevin Kreuzer ([@kreuzerk](https://github.com/kreuzerk))\n\nNote: this project is based on work in https://github.com/cartant/rxjs-tslint-rules/pull/107\n\n## Development\nClone the repository and install the dependencies with `npm install`.\n\nNote: using the build artifacts with `npm link` does not work correctly, \nsince there will be a mismatch between the typescript version used by the consumer code \nand the typescript version used by the lint rules code. \nTo test the package in a project, run \n```\nnpm run build\ncd dist\nnpm install --production\n``` \nThen copy the content of the `/dist` folder (including the `node_modules` folder) into `node_modules/@angular-extensions/lint-rules` \nin the consumer project.\n\n### Publish\nTo publish the package, run\n```\nnpm run publish-package\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fangular-extensions%2Flint-rules","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fangular-extensions%2Flint-rules","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fangular-extensions%2Flint-rules/lists"}