Tslint: Add option to allow linting of .js files

Created on 21 Jul 2015  路  15Comments  路  Source: palantir/tslint

This is a question/feature request.

I am working in a project where we have TypeScript for our main code and JavaScript for tests. I would like to lint both with tslint. As TypeScript is a superset of Javascript I do not see conceptual issues with that approach. I also think that using the same linter with the same configuration can help maintaining some consistency between the two.

Unfortunately, I get the following error message when trying to run tslint on a JavaScript file:

/home/xi/project/node_modules/tslint/bin/tslint-cli.js:43043
            this.limit = this.sourceFile.getFullWidth();
                                         ^
TypeError: Cannot call method 'getFullWidth' of undefined
    at EnableDisableRulesWalker.RuleWalker (/home/xi/project/node_modules/tslint/bin/tslint-cli.js:43043:42)
    at EnableDisableRulesWalker.SkippableTokenAwareRuleWalker (/home/xi/project/node_modules/tslint/bin/tslint-cli.js:43586:20)
    at new EnableDisableRulesWalker (/home/xi/project/node_modules/tslint/bin/tslint-cli.js:43707:20)
    at Linter.lint (/home/xi/project/node_modules/tslint/bin/tslint-cli.js:43976:31)
    at processFile (/home/xi/project/node_modules/tslint/bin/tslint-cli.js:44134:29)
    at Object.<anonymous> (/home/xi/project/node_modules/tslint/bin/tslint-cli.js:44144:5)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)

So there is really three things I would like to know:

  • Is it a good idea to use tslint for JavaScript?
  • Can you make tslint output a more useful error message in the case described above? How can I help with that?
  • Can you make tslint work with JavaScript? How can I help with that?
P1 Fixed Feature Request

Most helpful comment

Is it intentional that the --project flag does not seem to cause linting of .js files, even if tsconfig.json has allowJs set to true and an include config that includes them? For example, I have

{
  "compilerOptions": {
    "module": "commonjs",
    "noImplicitAny": false,
    "sourceMap": true,
    "outDir": "build",
    "lib": [
      "es6"
    ],
    "allowJs": true,
    "target": "es6"
  },
  "include": [
    "src/**/*"
  ]
}

and VS Code does run tslint on my JS files in src, but a tslint --project . in a terminal doesn't.

All 15 comments

Hmm, that's an interesting idea. Intuitively, it feels like you should go with something like eslint since that's more standard for JS linting, but as you mention, since TS is a superset of JS, theoretically tslint should also be able to accomplish this task.

The error you're seeing there is from the compiler API, which doesn't return a "source file" unless the filename is one of the valid TS extensions (.ts, .d.ts, and soon .tsx). We could potentially add an option to tslint that allows non-standard file extensions (including .js). I'll look into this, but if you want to try it out yourself, you can change the TS compiler options which are set in src/language/utils.ts: https://github.com/palantir/tslint/blob/master/src/language/utils.ts#L43

export function createCompilerOptions(): ts.CompilerOptions {
    return {
        allowNonTsExtensions: true, // add this line
        noResolve: true,
        target: ts.ScriptTarget.ES5
    };
}

I agree that tslint should show a more meaningful error message in this case where the source file couldn't load. I'll make an issue for that.

Thanks for the quick reply. Sounds very promising.

The workaround you mentioned works fine. Would be great if this could be turned into a proper option of some kind.

@gscshoyru @ashwinr
Any thoughts on the best way to do this?
I've added a command line/linter option for this, the complex part is that there's no good way right now to get this info from Linter to the places where it is needed. utils.ts contains the createCompilerOptions() method which needs to know if it should allow nonTS extensions or not. This method is used in a few places: when the tests and Linter are getting the source of files with the Lint.getSourceFile method and by some rules when calling createLanguageServiceHost.

A couple of the possible options:

  • createCompilerOptions could be changed to have parameters. A CompilerOptions object could be created by Linter and passed into getSourceFile each time it is called. Each rule could be passed a LanguageServiceHost object by Linter, which would remove the rule's need to know about compiler options.

The biggest downside to this is that there would be a lot of code change in a lot of places.

  • Linter could check the file extensions itself, and we could change the body of createCompilerOptions to always accept all extensions. Positives of this are that it would only be a couple lines of code added and very minimal change overall. Downsides are that it's an added responsibility of Linter and some of the changes in the first or third options could possibly be practical in the future.
  • Disseminate the ILinterOptions object somehow. Should the options be available to rules? Should the options be available in other places?

Leaving this open for further discussion and other requests (to gauge demand for this feature)

:+1: -- makes it "emotionally" easier to break developers into typescript by slipping the compiler (and a linter to go with it) into the build process without upsetting the applecart by doing the scary thing of actually using .ts extensions on files.

We plan to support this with TS 1.8, when the compiler will accept JS files through the --allowJs flag.

--allowJs is now available with TS 1.8. We should pick up this task again.

I would love to see this in as well, we have mixed TS and JS code and it would make it simpler if we had single linter, today using ESLint for JS files

requesting. that this be revisited once again. there's a lot of value in having a single lint capability.

I know that there are several people within Microsoft that would really like to see this issue resolved. So it is a high value for us.

Like @swar30 I have a project which will likely take a long time to transition to TS, having the ability to lint existing JS files during that transition is key.

We have great need for this. Migrating from babel and eslint was trickier than expected, and I'm a bit surprised with many small parts guarding against .js files since javascript is valid typescript code.

Is the fix right now to either manually patch tslint, or to rename all files to .ts extension? Or is there a better way?

Is it intentional that the --project flag does not seem to cause linting of .js files, even if tsconfig.json has allowJs set to true and an include config that includes them? For example, I have

{
  "compilerOptions": {
    "module": "commonjs",
    "noImplicitAny": false,
    "sourceMap": true,
    "outDir": "build",
    "lib": [
      "es6"
    ],
    "allowJs": true,
    "target": "es6"
  },
  "include": [
    "src/**/*"
  ]
}

and VS Code does run tslint on my JS files in src, but a tslint --project . in a terminal doesn't.

@ilkka sounds like a bug, can you file that separately?

@adidahiya just filed #2176.

Was this page helpful?
0 / 5 - 0 ratings