Tslint: Feature request: allow excluding files for specific rule

Created on 25 Mar 2016  ·  14Comments  ·  Source: palantir/tslint

The problem

I'd love to use "class-name" rule for all TypeScript files in my project, except one file, that is generated.

Current rule-options configuration format

Based on the documentation

Rule-options can be either a boolean true/false value denoting whether the rule is used or or a list [boolean, ...] where the boolean provides the same as in the non-list case, and the rest of the list are options to the rule that will determine what it checks for

So basically if i want to enable a rule, i have only two options in terms of rule-options format as shown here:

{
    "rules": {
        "class-name": true,
        "some-otherrule": [ true, arg1, arg2, arg3],
        ...
    }
}

So current format doesn't allow me to enable/disable specific rule for some files. If i wanted to exclude one file from being checked for errors, then i'd need to exclude that file for all rules.

Proposing additional rule-options configuration format

To allow excluding some file(s), advanced format

list [boolean, ...] where the boolean provides the same as in the non-list case
"some-otherrule": [ true, arg1, arg2, arg3],

could be extended so that first argument could be either boolean (as it is now) or array (or maybe object would be more clear compared to array?) that defines the files that are included/excluded.

I'm having in mind following syntax:
"some-otherrule": [ [includeGlobPattern, excludeGlobPattern], arg1, arg2, arg3],
for example
"some-otherrule": [ ["**/*", "**/generated.ts"], arg1, arg2, arg3],
or maybe if object would be used instead of array, follwogin syntax would be even easier:
"some-otherrule": [ {exclude: "**/generated.ts"}, arg1, arg2, arg3],
where include property would default to all files.

API Feature Request

Most helpful comment

I have the similar use case to @Chowarmaan.

I have test files *.test.ts in which I use dev dependencies, e.g. enzyme.
In tslint.json I have no-implicit-dependencies rule enabled and I want to disable this rule only for *.test.ts. Those test files are not all in the same folder so right now I have to put:

/* tslint:disable:no-implicit-dependencies */

at the beggining on each test file which is annoying

All 14 comments

Why don't you simply use:

/* tslint:disable:class-name */
// your generated file here

Does this not work?

That could indeed be used to make it work, but i filed this feature request in order to avoid modifying TypeScript generator (or add complexity to the generation process, by prepending generated files with tslint hints).
Using wildcards could be also beneficial to declaratively apply certain rules to only specific types of sources (main/unitTests/e2eTests) from tslint config, not from each file individually.

What do You think?

If you don't want to put comments in the file, then simply don't pass the file to tslint for linting, no?

It feels too heavyweight to be adding further options elsewhere when there are at least two means of achieving (partial) file exclusion

If you don't want to put comments in the file, then simply don't pass the file to tslint for linting, no?

That is exactly what I did, but now none of the rules are checked against excluded files.

It feels too heavyweight to be adding further options elsewhere when there are at least two means of achieving (partial) file exclusion

Yeah, that is what I anticipated as an answer ;) I also had some doubts - at least about the implementation (that I tried to keep as simple as possible).

In reality if this was to be implemented, it would be beneficial, if You could define constants for include and exclude patters, so You don't have to copy-past the same include/exclude pattern to all the rules where You want to filter the same files... I thought it might not be reasonable to make the example more complicated, but i had smth like that in mind:

{
    "constants": {
        "generatedFilesGlob": "**/generated.ts",
        "someOtherConstant": "some other value, that could be reused",
        ...
    },
    "rules": {
        "class-name": true,
        "some-otherrule": [ true, "arg1", "arg2", "arg3"],
        "rule-with-exclude": [ {"exclude": "generatedFilesGlob"}, "arg1", "arg2", "arg3"],
        ...
    }
}

but that would make the config file harder to parse. That took me to think about supporting js files for configuration, in addition to json files. For example:

const generatedFilesGlob = "**/generated.ts";
const allExceptGenerated = {exclude: generatedFilesGlob};
module.exports = {
    "rules": {
        "class-name": true,
        "some-otherrule": [ true, "arg1", "arg2", "arg3"],
        "rule-with-exclude": [ allExceptGenerated , "arg1", "arg2", "arg3"],
        "another-rule-with-the-same-exclude-pattern": [ allExceptGenerated , "arg1", "arg2", "arg3"],
        ...
    }
}

Using JavaScript files with modules (like gulp does) has another benefit - it allows commenting and isn't so strict about commas after last element in array or property in object.

@atsu85 interesting problem, but as @myitcv indicated I am reluctant to introduce file lists / globs into tslint.json because of the additional complexity / clutter in the config file. I do agree that TSLint should accept .js files for configuration in addition to simply .json files. I think that would help you address the use case -- you could set up two tslint build tasks (one for your regular sources, one for generated sources) and programmatically disable the class-name rule in one of them in the same tslintConfig.js file.

Filed #1065 for supporting .js config files

Fair enough, I'll close this issue in favor of just js config files

I have a use case for this that might make sense. I have test files (*.spec.ts) that I want to share most of my Typescript TSLint rules with, as the good coding practices apply to my tests as well.

However, I am testing some constants that are configured for the 'magic numbers' rule, so as not to have 5 in my code:
(Foo.substr(0,5);
but ensure it is a const
(Foo.substr(0,CONSTANT.FIVE);

As such, my test case for my const that is included from a common file, has a test to ensure that the const FIVE = 5 is always set. The test then expect(CONSTANTS.FIVE).toBe(5); fails the TSLint check since the magic number is used in the test. While I do not test all constants this way, I do want to check these numeric settings to ensure they do not change as they are expected to remain the specific size.

I could use two different TSLint configurations, but I really want to avoid them getting out of sync, or when adding a new rule, having to do it in multiple places.

I can do the /* tslint:disable:no-magic-numbers*/ for the one file for this specific tests that does work for me, but maybe some other cases in the tests file a common rule may need to be an exception, and instead of updating each *.spec.ts, the global pattern for the rule would work?

I have the similar use case to @Chowarmaan.

I have test files *.test.ts in which I use dev dependencies, e.g. enzyme.
In tslint.json I have no-implicit-dependencies rule enabled and I want to disable this rule only for *.test.ts. Those test files are not all in the same folder so right now I have to put:

/* tslint:disable:no-implicit-dependencies */

at the beggining on each test file which is annoying

This is a similar problem I run into as well as @RomanGotsiy where you can add disables at the top of the test files, but it does become cumbersome for each file. The exclude files would be helpful as you could exclude rules for a certain pattern files (test files, *.spec.ts) and have one clean configuration file that also allows you to simply enable more rules as you need them, and allow your tests to use them as well. Maybe the exclude files list would then just include the rules you want to disable, instead of adding the exclusion of files to each rule?

This. 100%. Having this problem with a monorepo where the test dependencies are listed in the workspace so tslint is crying about no-implicit-dependencies. It has to be done with a single configuration file so that IDE linting still works

I think this issue is also related to #3447

I'm going to add on to this stale thread as well. I am in the process of implementing an NgRx store in my Angular project. AOT build is yelling at me when I export a const reference to a function...

export const reducer = ( state = initialState, action: CurrentAction): CurrentState => {...}

Giving me a Function expressions are not supported in decorators in 'reducers' error. The problem comes in due to our linting rules. We have specifically enabled the only-arrow-functions rule across the project... it would be wonderful to add in pattern matching on the exclude to say exclude files of *.reducer.ts as an example for this specific rule but allow it to remain intact for every other file.

As it is, adding this line to the top of the file for every reducer file is cumbersome. There just seems that there should be a better way.

Necrobumping this too. I'm trying to add tslint-microsoft-contrib to a Vue project and a bunch of its rules bomb on .vue files; this could be a useful workaround for issues like this before the rule authors get around to ironing out those bugs - if they ever choose to. As it stands adding a comment to disable a bunch of rules into absolutely every Vue file I write is indeed cumbersome. It also makes sense to be a bit less strict in UI code or to deal with framework idioms, e.g. use of default exports

Was this page helpful?
0 / 5 - 0 ratings