Giter Site home page Giter Site logo

rxjs-tslint-rules's Introduction

rxjs-tslint-rules

GitHub License NPM version Downloads Build status dependency status devDependency Status peerDependency Status

TSLint is deprecated. All of the rules in this package - with the exception of the RxJS-version-5-only rules - have equivalent ESLint rules in the eslint-plugin-rxjs and eslint-plugin-rxjs-angular packages.

If you've arrived here looking for the TSLint rules that automatically convert RxJS version 5 code to version 6, you can find those rules here: rxjs-tslint.

That said, if you've not already done so, you might want to checkout the rules in this package, too. Using them, you can avoid potential problems and questionable practices.

What is it?

rxjs-tslint-rules is set of TSLint rules to:

  • help manage projects that use rxjs/add/... imports;
  • enforce or disallow Finnish notation; and
  • highlight other potential problems (see the rules for details).

Why might you need it?

When using imports that patch Observable:

import { Observable } from "rxjs/Observable";
import "rxjs/add/observable/of";
import "rxjs/add/operator/map";

TypeScript will see the merged declarations in all modules, making it difficult to find rxjs/add/... imports that are missing from modules in which patched observables and operators are used.

This can cause problems, as whether or not Observable is patched then depends upon the order in which the modules are executed.

The rules in this package can be used to highlight missing - or unused - imports and other potential problems with RxJS.

There are some examples of policies that can be implemented using particular rule combinations in:

And Christian Liebel has written about his approach to importing RxJS in his blog post:

Install

Install the package using NPM:

npm install rxjs-tslint-rules --save-dev

Update your tslint.json file to extend this package:

{
  "extends": [
    "rxjs-tslint-rules"
  ],
  "rules": {
    "rxjs-add": { "severity": "error" },
    "rxjs-no-unused-add": { "severity": "error" }
  }
}

Rules

WARNING: Before configuring any of the following rules, you should ensure that TSLint's no-unused-variable rule is not enabled in your configuration (or in any configuration that you extend). That rule has caused problems in the past - as it leaves the TypeScript program in an unstable state - and has a significant number of still-open issues. Consider using the no-unused-declaration rule from tslint-etc instead.

The package includes the following rules (none of which are enabled by default):

Rule Description Options
rxjs-add Enforces the importation of patched observables and operators used in the module. See below
rxjs-ban-observables Disallows the use of banned observables. See below
rxjs-ban-operators Disallows the use of banned operators. See below
rxjs-deep-operators Enforces deep importation from within rxjs/operators - e.g. rxjs/operators/map. Until Webpack does not require configuration for tree shaking to work, there will be situations where deep imports are preferred. None
rxjs-finnish Enforces the use of Finnish notation. See below
rxjs-just Enforces the use of a just alias for of. Some other Rx implementations use just and if that's your preference, this is the rule for you. (There was some discussion about deprecating of in favour of just, but it was decided to stick with of.) This rule includes a fixer. None
rxjs-no-add Disallows the importation of patched observables and operators. See below
rxjs-no-async-subscribe Disallows passing async functions to subscribe. None
rxjs-no-compat Disallows importation from locations that depend upon rxjs-compat. None
rxjs-no-connectable Disallows operators that return connectable observables. None
rxjs-no-create Disallows the calling of Observable.create. Use new Observable instead. None
rxjs-no-deep-operators Disallows deep importation from rxjs/operators. Deep imports won't be in available in RxJS v6. None
rxjs-no-do I do without do operators. Do you not? Well, do isn't always a code smell, but this rule can be useful as a warning. None
rxjs-no-explicit-generics Disallows the explicit specification of generic type arguments when calling operators. Rely upon TypeScript's inference instead. None
rxjs-no-exposed-subjects Disallows exposed subjects. In classes, Subject properties and methods that return a Subject must be private. See below
rxjs-no-finnish Disallows the use of Finnish notation. None
rxjs-no-ignored-error Disallows the calling of subscribe without specifying an error handler. None
rxjs-no-ignored-notifier Disallows observables not composed from the repeatWhen or retryWhen notifier. None
rxjs-no-ignored-observable Disallows the ignoring of observables returned by functions. None.
rxjs-no-ignored-replay-buffer Disallows using ReplaySubject, publishReplay or shareReplay without specifying the buffer size. None
rxjs-no-ignored-subscribe Disallows the calling of subscribe without specifying arguments. None
rxjs-no-ignored-subscription Disallows ignoring the subscription returned by subscribe. None
rxjs-no-ignored-takewhile-value Disallows the ignoring of the takeWhile value. None
rxjs-no-implicit-any-catch Like the no-implicit-any-catch rule in @typescript-eslint/eslint-plugin, but for the catchError operator instead of catch clauses.
rxjs-no-index Disallows importation from rxjs/index, etc. - for the reason, see this issue. None
rxjs-no-internal Disallows importation from rxjs/internal. None
rxjs-no-nested-subscribe Disallows the calling of subscribe within a subscribe callback. None
rxjs-no-operator Disallows importation from rxjs/operator. Useful if you prefer 'pipeable' operators - which are located in the operators directory. None
rxjs-no-patched Disallows the calling of patched methods. Methods must be imported and called explicitly - not via Observable or Observable.prototype. See below
rxjs-no-redundant-notify Disallows redundant notifications from completed or errored observables. None
rxjs-no-sharereplay Disallows using the shareReplay operator. Prior to version 6.4.0, that operator had some surprising behaviour. See below
rxjs-no-subclass Disallows subclassing RxJS classes. None
rxjs-no-subject-unsubscribe Disallows calling the unsubscribe method of a Subject instance. For an explanation of why this can be a problem, see this Stack Overflow answer. None
rxjs-no-subject-value Disallows accessing the value property of a BehaviorSubject instance. None
rxjs-no-tap An alias for rxjs-no-do. None
rxjs-no-topromise Forbids the use of the toPromise method. None
rxjs-no-unbound-methods Disallows the passing of unbound methods as callbacks. None
rxjs-no-unsafe-catch Disallows unsafe catch and catchError usage in NgRx effects and redux-observable epics. See below
rxjs-no-unsafe-first Disallows unsafe first and take usage in NgRx effects and redux-observable epics. None
rxjs-no-unsafe-scope Disallows the use of variables/properties from unsafe/outer scopes in operator callbacks. See below
rxjs-no-unsafe-subject-next Disallows unsafe optional next calls. The argument passed to next is optional, but not passing it is often unsafe. None
rxjs-no-unsafe-switchmap Disallows unsafe switchMap usage in NgRx effects and redux-observable epics. See below
rxjs-no-unsafe-takeuntil Disallows the application of operators after takeUntil. Operators placed after takeUntil can effect subscription leaks. See below
rxjs-no-unused-add Disallows the importation of patched observables or operators that are not used in the module. None
rxjs-no-wholesale Disallows the wholesale importation of rxjs or rxjs/Rx. None
rxjs-prefer-angular-async-pipe Disallows the calling of subscribe within an Angular component. None
rxjs-prefer-angular-composition Enforces the composition of subscriptions within an Angular component. The rule ensures that subscriptions are composed into a class-property Subscription and that the Subscription is unsubscribed in ngOnDestroy. (For an example, see the tests.) None
rxjs-prefer-angular-takeuntil Enforces the application of the takeUntil operator when calling subscribe within Angular components (and, optionally, within services, directives, and pipes). The rule (optionally) ensures that takeUntil is passed a class-property Subject and that the Subject is notified in ngOnDestroy. (For an example, see the tests.) See below
rxjs-prefer-observer Enforces the passing of observers to subscribe and tap. See this RxJS issue. See below
rxjs-suffix-subjects Disalllows subjects that don't end with the specified suffix option. See below
rxjs-throw-error Enforces the passing of Error values to error notifications. None

Options

rxjs-add

The rxjs-add rule takes an optional object with the property file. This is the path of the module - relative to the tsconfig.json - that imports the patched observables and operators.

For example:

"rules": {
  "rxjs-add": {
    "options": [{
      "allowElsewhere": false,
      "allowUnused": false,
      "file": "./source/rxjs-imports.ts"
    }],
    "severity": "error"
  }
}

Specifying the file option allows all of the patched observables and operators to be kept in a central location. Said module should be imported before other modules that use patched observables and operators. The importation of said module is not enforced; the rule only ensures that it imports observables and operators that are used in other modules.

If file is specified, the allowElsewhere and allowUnused options can be used to configure whether or not patched imports are allowed in other files and whether or not unused patched imports are allowed. Both allowElsewhere and allowUnused default to false.

Note that there is no file option for the rxjs-no-unused-add rule, so that rule should not be used in conjunction with the rxjs-add rule - if the file option is specified for the latter. Use the rxjs-add rule's allowUnused option instead.

If the file option is not specified, patched observables and operators must be imported in the modules in which they are used.

rxjs-ban-observables/operators

The rxjs-ban-observables and rxjs-ban-operators rules take an object containing keys that are the names of observables/operators and values that are either booleans or strings containing the explanation for the ban.

For example:

"rules": {
  "rxjs-ban-operators": {
    "options": [{
      "concat": "Use the concat factory function",
      "merge": "Use the merge factory function"
    }],
    "severity": "error"
  }
}

rxjs-finnish

The rxjs-finnish rule takes an optional object with optional functions, methods, parameters, properties and variables properties.

The properties are booleans and determine whether or not Finnish notation is enforced. All properties default to true.

For example, to enforce Finnish notation for variables only:

"rules": {
  "rxjs-finnish": {
    "options": [{
      "functions": false,
      "methods": false,
      "parameters": false,
      "properties": false,
      "variables": true
    }],
    "severity": "error"
  }
}

The options also support names and types properties that can be used to prevent the enforcement of Finnish notation for certain names or types. The properties themselves are objects with keys that are regular expressions and values that are booleans.

For example, the following configuration will not enforce Finnish notation for names ending with Stream or for the EventEmitter type:

"rules": {
  "rxjs-finnish": {
    "options": [{
      "names": {
          "Stream$": false
      },
      "types": {
          "^EventEmitter$": false
      }
    }],
    "severity": "error"
  }
}

If the types property is not specified, it will default to not enforcing Finnish notation for Angular's EventEmitter type.

rxjs-no-add and rxjs-no-patched

The rxjs-no-add and rxjs-no-patched rules take an optional object with the optional properties allowObservables and allowOperators. The properties can be specified as booleans - to allow or disallow all observables or operators - or as arrays of strings - to allow or disallow a subset of observables or operators.

For example:

"rules": {
  "rxjs-no-patched": {
    "options": [{
      "allowObservables": ["never", "throw"],
      "allowOperators": false
    }],
    "severity": "error"
  }
}

rxjs-no-exposed-subjects

The rule has an optional allowProtected property that can be specified - it defaults to false:

"rules": {
  "rxjs-no-exposed-subjects": {
    "options": [{
      "allowProtected": true
    }],
    "severity": "error"
  }
}

rxjs-no-sharereplay

This rule disallows the use of shareReplay as, prior to RxJS 6.4.0, it exhibited some surprising behaviour - see this PR for an explanation. In 6.4.0 and later, it's now possible to pass a configuration argument that includes a refCount property - so whether or not the implementation reference counts subscriptions can be determined by the caller.

The rule now has an optional allowConfig property that can be specified - it defaults to false - to allow shareReplay to be used as long as a config argument is passed:

"rules": {
  "rxjs-no-sharereplay": {
    "options": [{
      "allowConfig": true
    }],
    "severity": "error"
  }
}

rxjs-no-unsafe-catch

This rule disallows the usage of catch and catchError operators - in effects and epics - that are not within a flattening operator (switchMap, etc.). Such usage will see the effect or epic complete and stop dispatching actions after an error occurs. See Paul Lessing's article: Handling Errors in NgRx Effects.

The rule takes an optional object with an optional observable property. The property can be specifed as a regular expression string or as an array of words and is used to identify the action observables from which effects and epics are composed.

The following options are equivalent to the rule's default configuration:

"rules": {
  "rxjs-no-unsafe-catch": {
    "options": [{
      "observable": "action(s|\\$)?"
    }],
    "severity": "error"
  }
}

rxjs-no-unsafe-scope

The rule takes an optional object with optional allowDo, allowMethods, allowParameters, allowProperties, allowSubscribe and allowTap properties.

If the allowDo and allowTap options are true, the rule is not applied within do and tap operators respectively.

If the allowParameters option is true, referencing function parameters from outer scopes is allowed.

If the allowMethods option is true, calling methods via this is allowed.

If the allowProperties option is true, accessing properties via this is allowed.

If the allowSubscribe option is true, the rule is not applied within subscribe callbacks.

The following options are equivalent to the rule's default configuration:

"rules": {
  "rxjs-no-unsafe-scope": {
    "options": [{
      "allowDo": true,
      "allowMethods": true,
      "allowParameters": true,
      "allowProperties": false,
      "allowSubscribe": true,
      "allowTap": true
    }],
    "severity": "error"
  }
}

rxjs-no-unsafe-switchmap

The rxjs-no-unsafe-switchmap rule does its best to determine whether or not NgRx effects or redux-observable epics use the switchMap operator with actions for which it could be unsafe.

For example, it would be unsafe to use switchMap in an effect or epic that deletes a resource. If the user were to instigate another delete action whilst one was pending, the pending action would be cancelled and the pending delete might or might not occur. Victor Savkin has mentioned such scenarios in a tweet and I've written an article that's based on his tweet: Avoiding switchMap-Related Bugs.

The rule takes an optional object with optional allow, disallow and observable properties. The properties can be specifed as regular expression strings or as arrays of words.

If the allow option is specified, actions that do not match the regular expression or do not contain any of the specified words will effect an error if switchMap is used.

If the disallow option is specified, actions that match the regular expression or contain one of the specified words will effect an error if switchMap is used.

If neither option is specifed, the rule will default to a set of words are are likely to be present in any actions for which switchMap is unsafe.

The observable property is used to identify the action observables from which effects and epics are composed.

The following options are equivalent to the rule's default configuration:

"rules": {
  "rxjs-no-unsafe-switchmap": {
    "options": [{
      "disallow": ["add", "create", "delete", "post", "put", "remove", "set", "update"],
      "observable": "action(s|\\$)?"
    }],
    "severity": "error"
  }
}

To disallow or warn about all uses of switchMap within effects or epics, use a regular expression that will match all action types:

"rules": {
  "rxjs-no-unsafe-switchmap": {
    "options": [{
      "disallow": "."
    }],
    "severity": "error"
  }
}

rxjs-no-unsafe-takeuntil

The rule takes an optional object with optional alias and allow properties.

The alias property is an array containing the names of operators that aliases for takeUntil.

The allow property is an array containing the names of the operators that are allowed to follow takeUntil.

The following options are equivalent to the rule's default configuration:

"rules": {
  "rxjs-no-unsafe-takeuntil": {
    "options": [{
      "allow": ["count", "defaultIfEmpty", "endWith", "every", "finalize", "finally", "isEmpty", "last", "max", "min", "publish", "publishBehavior", "publishLast", "publishReplay", "reduce", "share", "shareReplay", "skipLast", "takeLast", "throwIfEmpty", "toArray"]
    }],
    "severity": "error"
  }
}

rxjs-prefer-angular-takeuntil

The rule takes an optional object with optional alias, checkDecorators and checkDestroy properties. The alias property is an array containing the names of operators that aliases for takeUntil. The checkDecorators property is an array containing the names of the decorators that determine whether or not a class is checked. And the checkDestroy property is a boolean that determines whether or not a Subject-based ngOnDestroy must be implemented.

rxjs-prefer-observer

The rule takes an optional object with an optional allowNext property. The property defaults to true, allowing a next callback to be passed instead of an observer. For more information, see this RxJS issue.

The following options are equivalent to the rule's default configuration:

"rules": {
  "rxjs-prefer-observer": {
    "options": [{
      "allowNext": true
    }],
    "severity": "error"
  }
}

rxjs-suffix-subjects

The rule takes an optional object with optional parameters, properties and variables properties. The properties are booleans and determine whether or not subjects used in those situations need a suffix.

parameters, properties and variables default to true, and the default suffix is 'Subject'.

The object also has optional types properties which are themselves objects containing keys that are regular expressions and values that are booleans - indicating whether suffixing is required for particular types.

The following options are equivalent to the rule's default configuration:

"rules": {
  "rxjs-suffix-subjects": {
    "options": [{
      "parameters": true,
      "properties": true,
      "suffix": "Subject",
      "variables": true
    }],
    "severity": "error"
  }
}

Gotchas

@angular/cli

Angular's CLI runs TSLint three times:

  • first, with application files from src/ (using src/tsconfig.app.json);
  • then with the test files from src/ (using src/tsconfig.spec.json);
  • and, finally, with files from e2e/ (using e2e/tsconfig.e2e.json).

If you are using the file option of the rxjs-add rule to ensure patched observables and operators are kept in a central location, there are some configuration changes that you should make:

  • I'd recommend switching off rxjs-add for the e2e linting, as the central file isn't necessary or appropriate. The simplest way to do this is to create an e2e/tslint.json file with the following content:

      {
        "extends": ["../tslint.json"],
        "rules": {
          "rxjs-add": { "severity": "off" }
        }
      }
    
  • And, for the test linting, I'd recommend adding the central file to the TypeScript configuration. If the central file is, say, src/rxjs.imports.ts, add that file to the "files" in src/tsconfig.spec.json:

      "files": [
        "rxjs.imports.ts",
        "test.ts"
      ]
    

    Alternatively, you can import rxjs.imports.ts directly into tests.ts, like this:

      import "./rxjs.imports";
    

With these changes, the rule should play nice with the CLI's running of TSLint. If you are using "allowUnused": false and receive errors about unused operators, you should make sure that files in which those operators are used are imported into at least one test. (The rule will walk all files included in the TypeScript program - not just the specs - so if an unused error is effected, the file using the unused operator is not present in the program and needs to be imported into a test.)

If you experience difficulties in configuring the rules with an @angular/cli-generated application, there is an example in this repo of a working configuration. To see the configuration changes that were made to a vanilla CLI application, have a look at this commit.

Observable.create

Observable.create is declared as a Function, which means that its return type is any. This results in an observable that's not seen by the rules, as they use TypeScript's TypeChecker to determine whether or not a call involves an observable.

The rule implementations include no special handling for this case, so if spurious errors are effected due to Observable.create, explicit typing can resolve them. For example:

const ob: Observable<number> = Observable.create((observer: Observer<number>) => { ...

rxjs-tslint-rules's People

Contributors

cartant avatar chrisguttandin avatar cito avatar greenkeeper[bot] avatar hoffination avatar macjohnny avatar maggie-x avatar mentatxx avatar milux avatar rafaelss95 avatar thorn0 avatar vakhaniya avatar zbream avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rxjs-tslint-rules's Issues

Add allowThis to rxjs-no-unsafe-scope rule

I am using observables in methods within classes. Some of the functions do things like:

of(1, 2, 3).pipe(
  concatMap(val => {
    return this.doSomething(val)
  })
)

With rxjs-no-unsafe-scope, it says "Unsafe scopes are forbidden".

I think it is due to this.doSomething(). Would be great if we can allowThis (and have it enabled by default)...just like allowParameters.

Differing behaviour on Linux and Windows

With imports like this:

import { of } from "rxjs/Observable/of";
const observable = of([1, 2]);
observable.subscribe();

The rxjs-no-ignored-subscribe rule effects failures on Windows, but not on Linux. The crux of the problem is that in isType, type.symbol is falsy, so no comparison can be made.

With imports like this:

import { Observable } from "rxjs/Observable";
import "rxjs/add/observable/of";
const observable = Observable.of([1, 2]);
observable.subscribe();

The behaviour is the same on both operating systems and the rule effects errors.

Why this is the case is a mystery, for the moment.

Implement automatic fixes

Just ran this on a project and got over 100 errors... The order of loading never broke it, but in fact it was a very fragile code. Would be awesome if it could automatically fix at least some issues, though.

The simplest one seems to be an unused import: it should remove the import.

For missing operators, I'm not sure how difficult it is to locate the place in code where these should be imported. After the last import in the file seems like a good place to start.

Whitelist for `rxjs-finnish`

Feature request

Allow whitelisting for rxjs-finnish, something like:

"rxjs-finnish": [
    true,
    "store"
]

So it will ignore those keywords

Unused patched operator in ./src/rxjs.imports.ts: switchMap

I'm getting this error with the switchMap operator.

I have plenty of other operators in rxjs.imports.ts so it's not any other issues except for switchMap.

I DO use switchMap in the application.

Perhaps this is the same problem with the flatMap issue? I'm not sure. I'm going to refactor the code to not use switchMap as the person who used it said they didn't use it for switchMap's intended purpose.

tslib is a dependency, but is not listed in package.json

I was working on an angular project using @angular/animations which has a dependency on tslib: ^1.7.1 which produces the following error when running the linter rules:

tslib_1.__makeTemplateObject is not a function
TypeError: tslib_1.__makeTemplateObject is not a function
    at /myproject/node_modules/rxjs-tslint-rules/dist/rules/rxjsAddRule.js:27:95
    at Object.<anonymous> (/myproject/node_modules/rxjs-tslint-rules/dist/rules/rxjsAddRule.js:35:2)
    at Module._compile (module.js:570:32)
    at Object.Module._extensions..js (module.js:579:10)
    at Module.load (module.js:487:32)
    at tryModuleLoad (module.js:446:12)
    at Function.Module._load (module.js:438:3)
    at Module.require (module.js:497:17)
    at require (internal/module.js:20:19)
    at loadRule (/myproject/node_modules/tslint/lib/ruleLoader.js:96:26)

This was resolved by removing node_modules/tslib and rerunning npm install which pulled down tslib 1.8.0 as a dependency of @angular/animations.

package.json for rxjs-tslint-rules doesn't list tslib as a dependency but it looks like it is. It should probably be added with the minimum version of 1.8.0.

TypeError: Cannot read property 'name' of undefined in rxjsFinnishRule

Hey, I'm liking the package!


However, I've tried out the rules in a couple of projects, and I've consistently run into the following error during linting:

The 'rxjs-finnish' rule threw an error in 'M:/Git/_public/rxjs-finnish-rule-issue/file.ts':
TypeError: Cannot read property 'name' of undefined
    at Walker.validateNode (M:\Git\_public\rxjs-finnish-rule-issue\node_modules\rxjs-tslint-rules\dist\rules\rxjsFinnishRule.js:169:49)
    at Walker.visitPropertyDeclaration (M:\Git\_public\rxjs-finnish-rule-issue\node_modules\rxjs-tslint-rules\dist\rules\rxjsFinnishRule.js:130:18)
    at Walker.SyntaxWalker.visitNode (M:\Git\_public\rxjs-finnish-rule-issue\node_modules\tslint\lib\language\walker\syntaxWalker.js:467:22)
    at M:\Git\_public\rxjs-finnish-rule-issue\node_modules\tslint\lib\language\walker\syntaxWalker.js:535:63
    at visitNodes (M:\Git\_public\rxjs-finnish-rule-issue\node_modules\typescript\lib\typescript.js:14006:30)
    at Object.forEachChild (M:\Git\_public\rxjs-finnish-rule-issue\node_modules\typescript\lib\typescript.js:14293:21)
    at Walker.SyntaxWalker.walkChildren (M:\Git\_public\rxjs-finnish-rule-issue\node_modules\tslint\lib\language\walker\syntaxWalker.js:535:12)
    at Walker.SyntaxWalker.visitClassDeclaration (M:\Git\_public\rxjs-finnish-rule-issue\node_modules\tslint\lib\language\walker\syntaxWalker.js:63:14)
    at Walker.SyntaxWalker.visitNode (M:\Git\_public\rxjs-finnish-rule-issue\node_modules\tslint\lib\language\walker\syntaxWalker.js:314:22)
    at M:\Git\_public\rxjs-finnish-rule-issue\node_modules\tslint\lib\language\walker\syntaxWalker.js:535:63

I've narrowed it down to being caused by the declaration of an optional property (which I use extensively with strictNullChecks enabled):

myOptionalProperty?: Subject<number> = new Subject<number>();


I've set up a minimal test repo for evaluation:

https://github.com/zbream/rxjs-finnish-rule-issue

You'll notice that if you comment out myOptionalProperty, everything works as expected. Also, no no-unused-variable in this project.

Wrong Error warnings for Unused patched operator in ./rxjs.imports.ts

Hello,

first I want to say thank you for your really good work here. 👍

So now to my problem:

I am using the rxjs-add rule like this:

"rxjs-add": {
    "options": [
        {
            "allowElsewhere": false,
            "allowUnused": false,
            "file": "./src/app/rxjs-operators.imports.ts"
        }
    ],
    "severity": "error"
},

So I use the approach to have all rxjs operators in on central file and nowhere else it is allowed to have them and don't have unused imports for the rxjs operators in the central rxjs operator import file.

That worked fine I just got the same error that was mentioned here: #5
I could fix that, but now I am getting linting errors for Unused patched operator although they are for sure used in my project.

I think this problem is related to the stuff that it is an angular project created with angular-cli and calling ng lint and that run's tslint three times (like you explained it):

  • first, with application files from src/;
  • then with the test files from src/;
  • and, finally, with files from e2e/.

So I think because not all application files are there for the second and third run I get the errors with the Unused patched operators.

For now, my only solution is to use "allowUnused": true.

Do you have an idea or hint how I could fix this problem?

TypeError: nodes.push is not a function

I've encountered error that I am not able to reproduce in any shareable way.

TypeError: nodes.push is not a function
    at Function.AddedWalker.add (C:\k\artemis\node_modules\rxjs-tslint-rules\dist\support\added-walker.js:19:15)
    at C:\k\artemis\node_modules\rxjs-tslint-rules\dist\support\used-walker.js:26:36
    at visitNode (C:\Users\bodingm\AppData\Roaming\npm\node_modules\typescript\lib\typescript.js:15944:20)
    at Object.forEachChild (C:\Users\bodingm\AppData\Roaming\npm\node_modules\typescript\lib\typescript.js:16087:24)
    at NodeObject.forEachChild (C:\Users\bodingm\AppData\Roaming\npm\node_modules\typescript\lib\typescript.js:88427:23)
    at Walker.UsedWalker.visitCallExpression (C:\k\artemis\node_modules\rxjs-tslint-rules\dist\support\used-walker.js:18:14)
    at Walker.SyntaxWalker.visitNode (C:\k\artemis\node_modules\tslint\lib\language\walker\syntaxWalker.js:305:22)
    at Walker.AddedWalker.visitNode (C:\k\artemis\node_modules\rxjs-tslint-rules\dist\support\added-walker.js:37:36)
    at C:\k\artemis\node_modules\tslint\lib\language\walker\syntaxWalker.js:535:63
    at visitNode (C:\k\artemis\node_modules\typescript\lib\typescript.js:15944:20)

Checking for existence of nodes.push worked well.

        if (nodes === undefined || !nodes.push) {
            map[key] = nodes = [];
        }

Add rule disallowing shareReplay & publishReplay without specifying buffer size

We use shareReplay (I'm aware of the related bug) to cache the results of computationally intensive transformations in the view (sorting, filtering, etc.). Occasionally, we forget to specify the buffer size, so the whole history is being cached and replayed. However, when subscribing with an async pipe you are usually only interested in the latest value.

It would we great if there was a rule disallowing the use of shareReplay and publishReplay without specifying a buffer size.

Unsafe scopes are forbidden from array's map() function

With rxjs-tslint-rules v4.7.0, and "rxjs-no-unsafe-scope": true, I am getting this rather unexpected "Unsafe scopes are forbidden".

Funny thing is, this whole chunk is NOT about observables.. just normal array map() so I would expect the rules to not take effect.

I only happens when the variable was destructured from parameter (e.g. notOk_mapAnArrayFromParam()). It is ok when used in ok_mapAnArray().

Maybe a bug?

  // this is ok
  ok_mapAnArray () {
    const q = '123'
    return [ 1, 2, 3 ].map(val => {
      // "q" is ok
      return `${q}-${val}`
    })
  }

  notOk_mapAnArrayFromParam (input: { q: string }) {
    const { q } = input
    return [ 1, 2, 3 ].map(val => {
      // "q" is NOT ok - complain about "Unsafe scopes are forbidden"
      return `${q}-${val}`
    })
  }

Angular CLI gotcha when an RxJS function is used only in a unit test

I have the following rxjs.imports.ts file in an Angular 4 project:

import 'rxjs/add/observable/of';

I have the following rule in the tslint.json file:

"rxjs-add": {
  "options": [{
    "file": "./src/rxjs.imports.ts"
  }],
  "severity": "error"
}

The following error is thrown when I run tslint:

ERROR: (rxjs-add) C:/Git/MyProject/src/rxjs.imports.ts[3, 1]: 
Unused patched observable in ./src/rxjs.imports.ts: of

I am using Observable.of(...) in my code, however only in one single .spec.ts file. It seems that the error is thrown during linting the application files, because if I remove the following block from the lint section of the .angular-cli.json file, the error disappears:

{
  "project": "src/tsconfig.app.json",
  "exclude": "**/node_modules/**"
},

Do you have any recommendation on how can I fix this, or this is just another gotcha that would be useful to add to the README?

Thank you!

No detection of inherited observables like @ngrx/store/Store

In case of inherited Observable logic the linting currently doesn't detect issues. Such cases are @ngrx/store/Store or @ngrx/store/Action.

For instance the following code would pass the linting, though a rxjs-no-operator rule is present:

...
import { Action, Store } from '@ngrx/store';
import { Actions, Effect } from '@ngrx/effects';

@Injectable()
export class PageEffects {
  constructor(
    private actions$: Actions,
    private store: Store<...>
  ) {}

@Effect()
myEffect$: Observable<Action> = this.actions$
    .ofType(...)
    .withLatestFrom(this.store.select(...).pluck('myPath'))
    .map(...);

Allow rxjs-no-patched to have exclusions?

Hi there, amazing work on these rules first of all!

Is it possible to allow the rxjs-no-patched rule to have exclusions to the rule? My use case is on Observable.of, Observable.never, and the rest that are in rxjs/add/observable that I want to exclude out of the rule — having functions like never() and throw() in the codebase can be confusing and we disallow renaming imports from another lint rule already.

I'm thinking of the same syntax as rxjs-add's file or a list of the patched methods to disallow. Let me know what you think.

Error: Cannot find ./src/rxjs.imports.ts

Getting this error every time although it works and shows lint errors.

Log:

Error: Cannot find ./src/rxjs.imports.ts
    at Walker.findSourceFile (/Users/Herc/Documents/RADAR/RADAR-Dashboard/node_modules/rxjs-tslint-rules/dist/rules/rxjsAddRule.js:134:15)
    at Walker.walkFile (/Users/Herc/Documents/RADAR/RADAR-Dashboard/node_modules/rxjs-tslint-rules/dist/rules/rxjsAddRule.js:144:35)
    at Walker.onSourceFileEnd (/Users/Herc/Documents/RADAR/RADAR-Dashboard/node_modules/rxjs-tslint-rules/dist/rules/rxjsAddRule.js:48:31)
    at Walker.AddedWalker.visitNode (/Users/Herc/Documents/RADAR/RADAR-Dashboard/node_modules/rxjs-tslint-rules/dist/support/added-walker.js:40:18)
    at Walker.SyntaxWalker.walk (/Users/Herc/Documents/RADAR/RADAR-Dashboard/node_modules/tslint/lib/language/walker/syntaxWalker.js:24:14)
    at Rule.AbstractRule.applyWithWalker (/Users/Herc/Documents/RADAR/RADAR-Dashboard/node_modules/tslint/lib/language/rule/abstractRule.js:31:16)
    at Rule.applyWithProgram (/Users/Herc/Documents/RADAR/RADAR-Dashboard/node_modules/rxjs-tslint-rules/dist/rules/rxjsAddRule.js:15:21)
    at Linter.applyRule (/Users/Herc/Documents/RADAR/RADAR-Dashboard/node_modules/tslint/lib/linter.js:176:29)
    at /Users/Herc/Documents/RADAR/RADAR-Dashboard/node_modules/tslint/lib/linter.js:121:85
    at Object.flatMap (/Users/Herc/Documents/RADAR/RADAR-Dashboard/node_modules/tslint/lib/utils.js:151:29)

ERROR: /Users/Herc/Documents/RADAR/RADAR-Dashboard/src/app/components/charts/chart-base/chart-base.component.ts[78, 8]: RxJS add import is missing from ./src/rxjs.imports.ts: debounceTime

Also had to add "no-unused-variable": false, to tslint for "allowUnused": false to work properly.

Best or more strict configuration of rxjs-tslint

What is the best configuration or more strict configuration of rxjs-tslint-rules?

        "rxjs-add": true,
        "rxjs-ban-observables": true,
        "rxjs-ban-operators": true,
        "rxjs-deep-operators": true,
        "rxjs-no-create": true,
        "rxjs-no-unsafe-catch": true,
        "rxjs-no-unsafe-first": true,
        "rxjs-no-unsafe-switchmap": true,
        "rxjs-no-unsafe-takeuntil": true,
        "rxjs-no-unused-add": true,
        "rxjs-no-wholesale": true,
        "rxjs-throw-error": true,

On tslint, all rules=true is the more strict method. This rules too?

Detect orphaned imports specified in the central import file

Hi @cartant,

thanks for your great plug-in. I really like the ability to specify a central import file using the rxjs-add rule options. I tried using this rule in combination with the rxjs-no-unused-add rule. Unfortunately, it now reports all imports of the central import file as unused, which I can totally understand, as the imports aren’t actually used in the central import file itself. However, it would be great if there is a rule (or an extension to rxjs-no-unused-add) that could detect imports which are specified in the central import file, but unused throughout the rest of the project. This would make it possible to detect imports in the central file that became orphaned in the meantime.

Would this be possible? Thanks in advance and keep up the good work.

TypeError: Cannot read property 'resolvedReturnType' of undefined

v. 3.16.1

Rule:

"rxjs-throw-error": {
      "severity": "error"
 }

Error:

	TypeError: Cannot read property 'resolvedReturnType' of undefined
    at Object.getReturnTypeOfSignature (C:\T\node_modules\typescript\lib\typescript.js:29729:28)
    at Walker.visitCallExpression (C:\T\node_modules\rxjs-tslint-rules\dist\rules\rxjsThrowErrorRule.js:50:42)
    at Walker.SyntaxWalker.visitNode (C:\T\node_modules\tslint\lib\language\walker\syntaxWalker.js:305:22)
    at C:\T\node_modules\tslint\lib\language\walker\syntaxWalker.js:535:63
    at visitNode (C:\T\node_modules\typescript\lib\typescript.js:12690:24)
    at Object.forEachChild (C:\T\node_modules\typescript\lib\typescript.js:12857:21)
    at Walker.SyntaxWalker.walkChildren (C:\T\node_modules\tslint\lib\language\walker\syntaxWalker.js:535:12)
    at Walker.SyntaxWalker.visitBinaryExpression (C:\T\node_modules\tslint\lib\language\walker\syntaxWalker.js:39:14)
    at Walker.SyntaxWalker.visitNode (C:\T\node_modules\tslint\lib\language\walker\syntaxWalker.js:293:22)
    at C:\T\node_modules\tslint\lib\language\walker\syntaxWalker.js:535:63

TypeError: Cannot read property 'kind' of undefined in rxjsFinnishRule

Hey there, added the rules to a project using

[email protected]
[email protected]

produced this stacktrace a couple of times:

TypeError: Cannot read property 'kind' of undefined
    at ./my-project/node_modules/rxjs-tslint-rules/dist/rules/rxjsFinnishRule.js:56:30
    at Array.forEach (native)
    at Walker.visitObjectLiteralExpression (./my-project/node_modules/rxjs-tslint-rules/dist/rules/rxjsFinnishRule.js:55:25)
    at Walker.SyntaxWalker.visitNode (./my-project/node_modules/tslint/lib/language/walker/syntaxWalker.js:449:22)
    at ./my-project/node_modules/tslint/lib/language/walker/syntaxWalker.js:535:63
    at visitNodes (./my-project/node_modules/typescript/lib/typescript.js:12699:30)
    at Object.forEachChild (./my-project/node_modules/typescript/lib/typescript.js:12830:21)
    at Walker.SyntaxWalker.walkChildren (./my-project/node_modules/tslint/lib/language/walker/syntaxWalker.js:535:12)
    at Walker.SyntaxWalker.visitCallExpression (./my-project/node_modules/tslint/lib/language/walker/syntaxWalker.js:54:14)
    at Walker.SyntaxWalker.visitNode (./my-project/node_modules/tslint/lib/language/walker/syntaxWalker.js:305:22)

The process does not crash and completes showing lint failures concerning some files in the project as if nothing had gone wrong. I tried to get some info on the root nodes but a few console.logs haven't yielded anything that would have helped to track down the source.

Not sure about `rxjs-no-unsafe-first`

I enabled most rules and fixed some bugs for which thanks!

All rules made sense in their purpose. Only rxjs-no-unsafe-first I wan't 100% sure about.

Is it because your effect will only run once / N times?

Beware of TSLint's no-unused-variable rule

I'm creating this issue as a reminder to myself and as a note that might be of use to others.

TSLint's no-unused-variable rule still seems to have problems - it has given me grief in the past. If it's enabled, the type information made available to rxjs-tslint-rules seems to change, resulting in the implementation sometimes being unable to determine whether or not an expression is an Observable. This can lead to false positives with the rxjs-no-unused-add rule, etc.

And it's not just rxjs-tslint-rules that's affected. With no-unused-variable enabled, I've seen false positives for TSLint's no-unnecessary-type-assertion rule, too.

rxjs-throw-error option to specifiy error names

I have in an Angular project warnings for rxjs-throw-error on code like this.

throwError(new HttpErrorResponse({}))

I have worked with subclassing Error on other projects before as well.

Would you consider a PR adding an option to set error names.

eg.

"rxjs-throw-error": {
  "options": { "errorNames": ["Error", "HttpErrorResponse"] },
  "severity": "warn",
}

The 'rxjs-no-unsafe-scope' rule threw an error

The 'rxjs-no-unsafe-scope' rule threw an error in './src/app/store/effects.ts':
TypeError: Cannot read property 'kind' of undefined
    at Object.isParameterDeclaration (./node_modules/rxjs-tslint-rules/node_modules/tsutils/typeguard/2.8/node.js:514:17)
    at Walker.isUnsafe (./node_modules/rxjs-tslint-rules/dist/rules/rxjsNoUnsafeScopeRule.js:84:45)
    at Walker.visitNode (./node_modules/rxjs-tslint-rules/dist/rules/rxjsNoUnsafeScopeRule.js:61:38)
    at ./node_modules/tslint/lib/language/walker/syntaxWalker.js:535:63
    at visitNode (./node_modules/typescript/lib/typescript.js:15779:24)
    at Object.forEachChild (./node_modules/typescript/lib/typescript.js:16009:21)
    at Walker.SyntaxWalker.walkChildren (./node_modules/tslint/lib/language/walker/syntaxWalker.js:535:12)
    at Walker.SyntaxWalker.visitConditionalExpression (./node_modules/tslint/lib/language/walker/syntaxWalker.js:72:14)
    at Walker.SyntaxWalker.visitNode (./node_modules/tslint/lib/language/walker/syntaxWalker.js:323:22)
    at Walker.visitNode (./node_modules/rxjs-tslint-rules/dist/rules/rxjsNoUnsafeScopeRule.js:65:36)

./src/app/store/effects.ts

/*  1 */ import { Inject, Injectable, LOCALE_ID } from '@angular/core';
/*  2 */ import { Actions, Effect, ofType } from '@ngrx/effects';
/*  3 */ import { Action } from '@ngrx/store';
/*  4 */ import { Observable, of } from 'rxjs';
/*  5 */ import { catchError, map, switchMap } from 'rxjs/operators';
/*  6 */ 
/*  7 */ import { CmLocale } from 'app/cm-common';
/*  8 */ 
/*  9 */ import { CmApiLabelService } from '../service';
/* 10 */ import * as featureActions from './actions';
/* 11 */ 
/* 12 */ @Injectable()
/* 13 */ export class AppStoreEffects {
/* 14 */   constructor(
/* 15 */     @Inject(LOCALE_ID) private localeId: CmLocale,
/* 16 */     private actions$: Actions,
/* 17 */     private labelService: CmApiLabelService,
/* 18 */   ) {}
/* 19 */ 
/* 20 */   @Effect()
/* 21 */   loadRequestEffect$: Observable<Action> = this.actions$.pipe(
/* 22 */     ofType<featureActions.LoadRequestAction>(
/* 23 */       featureActions.ActionTypes.LOAD_REQUEST,
/* 24 */     ),
/* 25 */     switchMap(({ payload: { applyLabelIdAsPrefix, labelId, localeId } }) =>
/* 26 */       this.labelService.getLabels(labelId, localeId || this.localeId).pipe(
/* 27 */         map(
/* 28 */           (labels) =>
/* 29 */             new featureActions.LoadSuccessAction({
/* 30 */               labels,
/* 31 */               prefix: applyLabelIdAsPrefix ? labelId : undefined,
/* 32 */             }),
/* 33 */         ),
/* 34 */         catchError((error) =>
/* 35 */           of(new featureActions.LoadFailureAction({ error })),
/* 36 */         ),
/* 37 */       ),
/* 38 */     ),
/* 39 */   );
/* 40 */ }

Cannot find rxjs-imports.ts in the compiled program

Hello

I have setup rxjs-tslint-rules with Angular CLI 1.4.7. I have followed the README with the Angular Gotchas as well as this blogpost https://christianliebel.com/2017/07/import-rxjs-correctly/.

I ended up with the following file updates:

  • In tsconfig.json I added the following:
"rules": {
    "rxjs-add": {
      "options": [
        {
          "allowElsewhere": false,
          "allowUnused": false,
          "file": "./src/rxjs-imports.ts"
        }
      ],
      "severity": "error"
    }
  }

In my tslint.json I added:

"extends": [
    "rxjs-tslint-rules"
  ],
  "rules": {
    "rxjs-add": {
      "severity": "error",
      "options": [
        {
          "allowElsewhere": false,
          "allowUnused": false,
          "file": "./src/rxjs-imports.ts"
        }
      ]
    },
    "rxjs-no-unused-add": {
      "severity": "error"
    },
}

Then I created a rxjs-imports.ts file:

import 'rxjs/add/observable/interval';
import 'rxjs/add/operator/map';

I then imported this file in my main.ts with the following import statement:

import 'rxjs-imports.ts'

Furthermore I had to pass --type-check to the linting task. When I run npm run lint --type-check I get the following error:

> ng lint --type-check

Error: Cannot find '/users/kevinkreuzer/desktop/central/rxjscentral/src/rxjs-imports.ts' in the compiled program. Has it been imported?
    at Walker.findSourceFile (/Users/kevinkreuzer/Desktop/central/rxjsCentral/node_modules/rxjs-tslint-rules/dist/rules/rxjsAddRule.js:136:15)
    at Walker.walkFile (/Users/kevinkreuzer/Desktop/central/rxjsCentral/node_modules/rxjs-tslint-rules/dist/rules/rxjsAddRule.js:146:35)
    at Walker.onSourceFileEnd (/Users/kevinkreuzer/Desktop/central/rxjsCentral/node_modules/rxjs-tslint-rules/dist/rules/rxjsAddRule.js:48:31)
    at Walker.AddedWalker.visitNode (/Users/kevinkreuzer/Desktop/central/rxjsCentral/node_modules/rxjs-tslint-rules/dist/support/added-walker.js:41:18)
    at Walker.SyntaxWalker.walk (/Users/kevinkreuzer/Desktop/central/rxjsCentral/node_modules/tslint/lib/language/walker/syntaxWalker.js:24:14)
    at Rule.AbstractRule.applyWithWalker (/Users/kevinkreuzer/Desktop/central/rxjsCentral/node_modules/tslint/lib/language/rule/abstractRule.js:31:16)
    at Rule.applyWithProgram (/Users/kevinkreuzer/Desktop/central/rxjsCentral/node_modules/rxjs-tslint-rules/dist/rules/rxjsAddRule.js:15:21)
    at Linter.applyRule (/Users/kevinkreuzer/Desktop/central/rxjsCentral/node_modules/tslint/lib/linter.js:176:29)
    at /Users/kevinkreuzer/Desktop/central/rxjsCentral/node_modules/tslint/lib/linter.js:121:85
    at Object.flatMap (/Users/kevinkreuzer/Desktop/central/rxjsCentral/node_modules/tslint/lib/utils.js:151:29)

ERROR: /Users/kevinkreuzer/Desktop/central/rxjsCentral/src/rxjs-imports.ts[1, 1]: RxJS add import is unused: interval
ERROR: /Users/kevinkreuzer/Desktop/central/rxjsCentral/src/rxjs-imports.ts[2, 1]: RxJS add import is unused: map
ERROR: /Users/kevinkreuzer/Desktop/central/rxjsCentral/src/rxjs-imports.ts[2, 32]: file should end with a newline

The path where it is looking for the file seems to be correct. Am I missing something? I thought by including the rxjs-imports.ts in my main.ts this file should be included in the compiled program.

rxjs-add false positive when type is not specified explicitly

I have the following function in an Angular 4 service class:

public get(url: string): Promise<Response> {
  return this._http.get(url).toPromise();
}

Note, that the get function returns an Observable, but this type name is not appearing in the code explicitly.
The .toPromise() function of Observable is imported in rxjs.imports.ts like this:

import 'rxjs/add/operator/toPromise';

And I have the following rule in tslint.json:

"rxjs-add": {
  "options": [{
      "file": "./src/rxjs.imports.ts"
  }],
  "severity": "error"
}

This triggers the following error when running tslint, which seems to be a false alarm:

ERROR: (rxjs-add) C:/Git/MyProject/src/rxjs.imports.ts[4, 1]: 
Unused patched operator in ./src/rxjs.imports.ts: toPromise

Thank you for creating and maintaining this library, Nicholas!

György

TypeError: Cannot read property 'getDeclarations' of undefined

"rxjs-no-unsafe-scope": {
  "severity": "error"
}

TypeError: Cannot read property 'getDeclarations' of undefined
at Walker.isUnsafe (C:\T\node_modules\rxjs-tslint-rules\dist\rules\rxjsNoUnsafeScopeRule.js:96:34)
at Walker.visitNode (C:\T\node_modules\rxjs-tslint-rules\dist\rules\rxjsNoUnsafeScopeRule.js:81:38)
at C:\T\node_modules\tslint\lib\language\walker\syntaxWalker.js:535:63
at visitNode (C:\T\node_modules\typescript\lib\typescript.js:12690:24)
at Object.forEachChild (C:\T\node_modules\typescript\lib\typescript.js:12822:21)
at Walker.SyntaxWalker.walkChildren (C:\T\node_modules\tslint\lib\language\walker\syntaxWalker.js:535:12)
at Walker.SyntaxWalker.visitPropertyAccessExpression (C:\T\node_modules\tslint\lib\language\walker\syntaxWalker.js:207:14)
at Walker.SyntaxWalker.visitNode (C:\T\node_modules\tslint\lib\language\walker\syntaxWalker.js:461:22)
at Walker.visitNode (C:\T\node_modules\rxjs-tslint-rules\dist\rules\rxjsNoUnsafeScopeRule.js:85:36)
at C:\T\node_modules\tslint\lib\language\walker\syntaxWalker.js:535:63

serving entry file with all imports

Hi @cartant

this looks like a really good solution.

However until the IDEs will support automatic import of rxjs operators and stuff, this is not really comfortable to use.

What I'd like to propose (and of course to have) is another setting in e.g. tslint.json that allows to specify the file, let's call it rxjs-modules.ts for instance, that contains all rxjs operators etc. for the particular project.

Of course, this rxjs-modules.ts should be imported in the beginning of main.ts so there is no race condition problem.

Is it possible to do so? Just to sum up:

  1. We have some file e.g. rxjs-modules.ts which we set up as another property in tslint.json
  2. This file is used to check every file in the project and it is end-programmer's responsibility to import this file before all other imports in his entry file.

Then everybody can decide for his project: whether to import everything inside of one single file or import it in each file separately.

rxjs-just rationale

It would be helpful to a have a sentence or so describing the rationale for this new rule in the readme. Should just be generally preferred as a best practice / is or deprecated, or is this just a rule for projects that happen to have already standardized on just for whatever reason?

(Neither of those words is very googleable, so finding those answers myself isn't very straightforward.)

rxjs-no-unsafe-switchmap doesn't seem to work

I have set the rxjs-no-unsafe-switchmap to true in the tslint.json file of my Angular project, but when I run ng lint I get no errors. I initially configured it as:

"rules": {
"rxjs-no-unsafe-switchmap": {
"options": [{
"disallow": ["add", "create", "delete", "post", "put", "remove", "set", "update"],
"observable": "action(s|\$)?"
}],
"severity": "error"
}
}

But to no avail, so I removed everything else from my tslint file and left only:

 {
     "extends": [
         "rxjs-tslint-rules"
     ],
     "rules": {
         "rxjs-no-unsafe-switchmap": {
             "options": [{
                 "disallow": "."
             }],
             "severity": "error"
         },
         "rxjs-no-create": true
     }
 }

Running ng lint does detect errors related to the rxjs-no-create rule, but nothing related to switchmaps.

I have, in my effects:

 @Effect()
     deleteTest = this.actions
         .pipe(
             ofType(testActions.type.DELETE_TEST),
             map((action: testActions.DeleteTestAction) => action.payload),
             switchMap((payload: { id: number }) =>
                 this.cs.deleteTest(payload.id)
                     .pipe(
                         map(() =>
                             new testActions.DeleteTestSuccessAction({ id: payload.id })
                         ),
                         catchError(() => of(new testActions.DeleteTestFailureAction()))
                     )
             )
         );

As I understand it, this should be displaying a lint error.

`rxjs-no-unsafe-takeuntil` doesn't work for all cases.

I specifically applied these rules to our project interested in the rxjs-no-unsafe-takeuntil rule, knowing there are multiple sports where it's used. However, upon applying, to my suprise it only surfaced a few use cases.

I thought there might be some special-case handling depending on the operator, but I took a peek at the rule implementation and didn't see anything that stood out to me as to why the rule wouldn't work in our case.

To give an example that I see in our codebase:

class MyClass {

   ...

   private _registerQuery (query: string): Query {
    if (this._queries.has(query)) {
      return this._queries.get(query)!;
    }

    const mql: MediaQueryList = this.mediaMatcher.matchMedia(query);
    const queryObservable = fromEventPattern<MediaQueryList>(
      (listener: Function) => { mql.addListener((e: MediaQueryList) => listener(e)); },
      (listener: Function) => { mql.removeListener((e: MediaQueryList) => listener(e)); }
    ).pipe(
      takeUntil(this._destroy),
      startWith(mql),
      map((nextMql: MediaQueryList) => ({ matches: nextMql.matches }))
    );

    const output = { observable: queryObservable, mql: mql };
    this._queries.set(query, output);
    return output;
  }
}

Happy to take more time to actually debug afterwards, but thought I'd document in the meantime. The use cases that we have don't seem out of the ordinary, which is why I was surprised.

THANK YOU

It has been such an amazing help on a huge Angular project...

Would be really awesome with auto fix but still, super helpful.

Thanks a lot!

Only allow add imports in central file

It would also be interesting to allow imports in the central import file exclusively, but not in the other files in the project. Maybe using an additional option for either rxjs-add or rxjs-no-add.

So this would be allowed:
src/rxjs-imports.ts

import 'rxjs/add/foobar';

But this wouldn’t:
src/component/foo.ts

import 'rxjs/add/jabber';

No errors at all

I added rxjs-tslint-rules to my dev dependencies. Then I added to my tslint.json file:

  "extends": [
    "tslint:recommended",
    "tslint-config-prettier",
    "rxjs-tslint-rules"
  ],
  ...
  rules: {
     "rxjs-add": {
      "options": {
        "allowElsewhere": false,
        "allowUnused": false,
        "file": "./src/rxjs-imports.ts"
      },
      "severity": "error"
    }
  }

I removed no-unused-variable declaration from tslint.json.

Right now, in the project, rxjs imports are in many files. I want to force the rule to have one central file with imports. However, when I run linting:

npm run tslint "src/**/*.ts"

I see a warning: Warning: The 'rxjs-add' rule requires type information.
I see no errors at all. Moreover, VS Code shows no errors. I'm not using Angular CLI.

tslint version: 5.8.0
rxjs-tslint-rules: version 4.7.0

Wrong detection of unused operator

I use this configuration for tslint :

"rxjs-add": {
    "options": [{
        "allowElsewhere": false,
        "allowUnused": false,
        "file": "./src/rxjs-imports.ts"
    }],
    "severity": "error"
},
"rxjs-no-wholesale": {
    "severity": "error"
}

It detects an unused operator in a file:

ERROR: /Users/.../app/src/rxjs-imports.ts[8, 1]: Unused patched observable in ./src/rxjs-imports.ts: from

If I comment this operator in my global file, I then have the following error :

ERROR: /Users/.../app/src/app/shared/store/error.actions.ts[60, 33]: RxJS add import is missing from ./src/rxjs-imports.ts: from

Which is correct since the from operator is used in this file.

What's the recommended method for using rxjs-add in a modularized Angular app?

I've used this package along with this configuration here in my tslint.json:

"rxjs-add": {
      "options": [
        {
          "allowElsewhere": false,
          "allowUnused": false,
          "file": "./src/rxjs.imports.ts"
        }
      ],
      "severity": "error"
    }

It has worked perfectly so far, with a centralized rxjs.imports file to keep track of all the operators and observable methods.

However, since I've refactored into using an ngModule style of file structure (for lazy loading and just tidier file structures), the Unused patched observable in ./src/rxjs.imports.ts: fromEvent errors are firing off falsely.

Here's the article I used to modularize: https://medium.com/@motcowley/angular-folder-structure-d1809be95542.

The structure now looks like this for src/app

- app.module.ts
- app.component.ts
- modules
    - module1
       - components
       - pages
       module1.service.ts
       module1.module.ts
       module1.routes.ts

    - module2
       - components
       - pages
       module2.service.ts
       module2.module.ts
       module2.routes.ts
- shared
   - components
   - mocks
   - models
   - ...

What kind of configuration do I need to make in order to point them to my modules?

Mind you, the app works perfectly. It's just the allowUnused rules that are falsely firing.

The only recognized rule is rxjs-no-add

I am trying to migrate to using pipeable operators and I added the rules as described in the "Switching to lettable operators" section here.

The rxjs-no-add rule is working:

image

But there are no linting errors or warnings with any of the other rules. The no-unused-variable rule is not enabled in my project.

Error: Cannot find module 'rxjs'

We have a shared TSLint config that is used company-wide in all TS projects through an npm package. It includes rxjs-tslint-rules as a dependency and enables the rules. When using it on a project that does not use rxjs, linting errors with this exception:

{ Error: Cannot find module 'rxjs' from '/home/travis/build/felixfbecker/cli-highlight/node_modules/rxjs-tslint-rules/dist/support'
    at Function.module.exports [as sync] (/home/travis/build/felixfbecker/cli-highlight/node_modules/resolve/lib/sync.js:40:15)
    at read (/home/travis/build/felixfbecker/cli-highlight/node_modules/rxjs-tslint-rules/dist/support/knowns.js:9:25)
    at Object.<anonymous> (/home/travis/build/felixfbecker/cli-highlight/node_modules/rxjs-tslint-rules/dist/support/knowns.js:24:28)
    at Module._compile (module.js:635:30)
    at Object.Module._extensions..js (module.js:646:10)
    at Module.load (module.js:554:32)
    at tryModuleLoad (module.js:497:12)
    at Function.Module._load (module.js:489:3)
    at Module.require (module.js:579:17)
    at require (internal/module.js:11:18) code: 'MODULE_NOT_FOUND' }

Missing known-observable and -operator

I have noticed that there are some missing observable and operator eg. race observable and shareReplay operator.
There could be some more, I haven't checked that.

Does rxjs-no-wholesale still had a life meaning ?

According the rxjs v6 breaking changes, a lot of features will no longer be available with a deep import.

So, we will have to import interface like this:

import { Observable, Subject } from 'rxjs';

Instead of:

import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';

As the rxjs-no-wholesale rule suggest.

So, does we still need this rule for the next rxjs release ?

Error in 4.4.0 with rxjs-just rule

I have this error when I updated to version 4.4.0

Error: Cannot find module '@phenomnomnominal/tsquery'
    at Function.Module._resolveFilename (module.js:547:15)
    at Function.Module._load (module.js:474:25)
    at Module.require (module.js:596:17)
    at require (internal/module.js:11:18)
    at Object.<anonymous> (...\node_modules\rxjs-tslint-rules\dist\rules\rxjsJustRule.js:6:17)
    at Module._compile (module.js:652:30)
    at Object.Module._extensions..js (module.js:663:10)
    at Module.load (module.js:565:32)
    at tryModuleLoad (module.js:505:12)
    at Function.Module._load (module.js:497:3)

rxjs-no-unsafe-scope not working with generics

I noticed that this rule does not work when there's generics in the function call. If I call getProduct() without <Product>, it works. I think it's a bug.

Here's a simple example:

import { of } from 'rxjs'
import { concatMap } from 'rxjs/operators'

interface Product {
  title: string
}

class MyProductService {
  getProduct<T> () {
    return of(null)
  }

  withGeneric_notOk () {
    return of(null).pipe(
      // Unsafe scopes are forbidden
      // "rxjs-no-unsafe-scope": {
      //   "options": [
      //     {
      //       "allowDo": false,
      //       "allowMethods": true,
      //       "allowParameters": true,
      //       "allowProperties": true,
      //       "allowTap": false
      //     }
      //   ]
      // }
      concatMap(() => this.getProduct<Product>())
    )
  }

  noGeneric_ok () {
    return of(null).pipe(
      concatMap(() => this.getProduct())
    )
  }
}

Version 10 of node.js has been released

Version 10 of Node.js (code name Dubnium) has been released! 🎊

To see what happens to your code in Node.js 10, Greenkeeper has created a branch with the following changes:

  • Added the new Node.js version to your .travis.yml

If you’re interested in upgrading this repo to Node.js 10, you can open a PR with these changes. Please note that this issue is just intended as a friendly reminder and the PR as a possible starting point for getting your code running on Node.js 10.

More information on this issue

Greenkeeper has checked the engines key in any package.json file, the .nvmrc file, and the .travis.yml file, if present.

  • engines was only updated if it defined a single version, not a range.
  • .nvmrc was updated to Node.js 10
  • .travis.yml was only changed if there was a root-level node_js that didn’t already include Node.js 10, such as node or lts/*. In this case, the new version was appended to the list. We didn’t touch job or matrix configurations because these tend to be quite specific and complex, and it’s difficult to infer what the intentions were.

For many simpler .travis.yml configurations, this PR should suffice as-is, but depending on what you’re doing it may require additional work or may not be applicable at all. We’re also aware that you may have good reasons to not update to Node.js 10, which is why this was sent as an issue and not a pull request. Feel free to delete it without comment, I’m a humble robot and won’t feel rejected 🤖


FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

Error: Cannot find 'rxjs.imports.ts' in the compiled program. Has it been imported?

I'm getting this error when running the linter:

Error: Cannot find '/path/to/app/src/rxjs.imports.ts' in the compiled program. Has it been imported?
    at Walker.findSourceFile (/path/to/app/node_modules/rxjs-tslint-rules/dist/rules/rxjsAddRule.js:136:15)
    at Walker.walkFile (/path/to/app/node_modules/rxjs-tslint-rules/dist/rules/rxjsAddRule.js:146:35)
    at Walker.onSourceFileEnd (/path/to/app/node_modules/rxjs-tslint-rules/dist/rules/rxjsAddRule.js:48:31)
    at Walker.AddedWalker.visitNode (/path/to/app/node_modules/rxjs-tslint-rules/dist/support/added-walker.js:41:18)
    at Walker.SyntaxWalker.walk (/path/to/app/node_modules/tslint/lib/language/walker/syntaxWalker.js:24:14)
    at Rule.AbstractRule.applyWithWalker (/path/to/app/node_modules/tslint/lib/language/rule/abstractRule.js:31:16)
    at Rule.applyWithProgram (/path/to/app/node_modules/rxjs-tslint-rules/dist/rules/rxjsAddRule.js:15:21)
    at Linter.applyRule (/path/to/app/node_modules/tslint/lib/linter.js:174:29)
    at /path/to/app/node_modules/tslint/lib/linter.js:119:85
    at Object.flatMap (/path/to/app/node_modules/tslint/lib/utils.js:151:29)

The linter found the errors though and I could fix the problems, but I'm still getting this. I have added the rxjs-add ruleset following the instructions in the README file and I've imported my rxjs.imports.ts file in main.ts, just like in the example code.

Operators matched by name only

As noted in #54, numerous rules - that apply to operators - match functions using known operator names. The rules should instead look at function return types to avoid matching functions like Array.prototype.map and to also match user-land operators.

Reorganise the README into rule categories

There are considerably more rules in this package than when it started out and the README.md is now pretty unwieldy. Organise it. And, when doing this, make sure that rules have sensible type metadata.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.