Tslint: TypeError: ruleConfiguration.forEach is not a function

Created on 31 Mar 2017  路  8Comments  路  Source: palantir/tslint

Bug Report

  • __TSLint version__: 5.0.0
  • __TypeScript version__: 2.2.2
  • __Node version__: v6.9.1
  • __Running TSLint via__: Node.js API

Usage

import { Linter, ILinterOptions } from 'tslint';
import fs from 'fs-extra-promise';
import globby from 'globby';
import { project } from '../project';

const tslintConfig = require('../tslint.json');
const lintOptions: ILinterOptions = {
  formatter: 'codeFrame',
  rulesDirectory: [],
  formattersDirectory: '',
  fix: false
};
const defaultFilePatterns = [
  `${project.srcDir}/**/*.ts`
];

export async function lintAsync(filePatterns = defaultFilePatterns) {
  const filePaths = await globby(filePatterns);
  const contents = await Promise.all(filePaths.map(filePath => fs.readFileAsync(filePath, 'utf8')));
  const results = filePaths.map((filePath, index) => {
    const content = contents[index];
    const linter = new Linter(lintOptions);
    linter.lint(filePath, content, tslintConfig);
    return linter.getResult();
  });

  const errors = results.filter(result => !!result.errorCount);
  return errors;
}

Actual behavior

TypeError: ruleConfiguration.forEach is not a function
    at Object.convertRuleOptions (./node_modules/tslint/lib/configuration.js:357:23)

ruleConfiguration.forEach seems to expect a Map. Problem appeared after upgrading to v5. My node version should support Map:

$ node
> new Map()
Map {}

Expected behavior

No error?

Documentation P2 Fixed Bug

Most helpful comment

Hi,
What is the fix for this?
I am still having in issue using tslint-loader for webpack 2, trying to load my tslint.json in my tslint-loader configuration.

I tracked the issue down and my conclusion is that it fails because we pass in a dictionary of lint rules which is being iterated by a forEach in the function convertRuleOptions (file lib/configuration.js:355). However, it is a dictionary object, not an Array. So forEach is not available.
I tried converting rules in tslint-loader to an array of rule objects, but then the function fails since ruleName is expected to be a string name and not the array index.

I posted a possible fix by changing the forEach to an Object.keys() iteration. This seems to solve the issue but I am not sure if it is a symptom fix only.
Check other package for fix: https://github.com/wbuchwalter/tslint-loader/issues/73

Please advice?

All 8 comments

Okay... Maybe I need this line const configLoad = Configuration.findConfiguration(configurationFilename, filename);? Because IConfigurationFile has a rules: Map<string, Partial<IOptions>>; property.

yeah you're using an untyped import require("../tslint.json") that does _not_ give you an IConfigurationFile. check out how runner.ts uses findConfiguration

Library usage section of the README covers this

... but it looks like the docs site is outdated :( https://palantir.github.io/tslint/usage/library/

Library usage section of the README covers this
... but it looks like the docs site is outdated :( https://palantir.github.io/tslint/usage/library/

Yes, I saw this later yesterday. Would this be a correct usage example for README.md...?

import { Linter, Configuration } from "tslint";
import * as fs from "fs";

const fileName = "Specify input file name";
const configurationFilename = "Specify configuration file name";
const options = {
    formatter: "json",
    rulesDirectory: "customRules/",
    formattersDirectory: "customFormatters/"
};

const fileContents = fs.readFileSync(fileName, "utf8");
const linter = new Linter(options);
-const configLoad = Configuration.findConfiguration(configurationFilename, filename);
-const result = linter.lint(fileName, fileContents, configLoad.results);
+const configLoad = Configuration.findConfiguration(configurationFilename, fileName);
+linter.lint(fileName, fileContents, configLoad.results);
+const result = linter.getResult();

Hi,
What is the fix for this?
I am still having in issue using tslint-loader for webpack 2, trying to load my tslint.json in my tslint-loader configuration.

I tracked the issue down and my conclusion is that it fails because we pass in a dictionary of lint rules which is being iterated by a forEach in the function convertRuleOptions (file lib/configuration.js:355). However, it is a dictionary object, not an Array. So forEach is not available.
I tried converting rules in tslint-loader to an array of rule objects, but then the function fails since ruleName is expected to be a string name and not the array index.

I posted a possible fix by changing the forEach to an Object.keys() iteration. This seems to solve the issue but I am not sure if it is a symptom fix only.
Check other package for fix: https://github.com/wbuchwalter/tslint-loader/issues/73

Please advice?

If you look at the code, you'll see that the raw configuration file goes through the parseConfigFile function.

So you can't simply provide a JSON/Object as configuration.

The following example demonstrates correct usage (albeit with plain objects):

const tslint = require('tslint')

export const lint = text => {
  const options = {
    fix: false,
    formatter: 'json',
  }

  const rawConfig = tslint.Configuration.EMPTY_CONFIG

  rawConfig.rules = {
    semicolon: [true, 'always'],
  }

  const config = tslint.Configuration.parseConfigFile(rawConfig)

  const linter = new tslint.Linter(options)
  linter.lint('test.ts', text, config)
  return linter.getResult()
}

I was getting this because I installed prettier-tslint globally, when it should actually be in devDependencies.

Was this page helpful?
0 / 5 - 0 ratings