CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-tslint

An extensible static analysis linter for the TypeScript language

Pending
Overview
Eval results
Files

linting.mddocs/

Core Linting

This document covers TSLint's core linting functionality, including the Linter class, programmatic usage patterns, and integration with TypeScript programs.

Linter Class

The Linter class is TSLint's primary interface for programmatic linting operations.

Constructor

class Linter {
    constructor(options: ILinterOptions, program?: ts.Program)
}
interface ILinterOptions {
    fix: boolean;
    formatter?: string | FormatterConstructor;
    formattersDirectory?: string;
    quiet?: boolean;
    rulesDirectory?: string | string[];
}

Parameters:

  • options.fix - Enable automatic fixing of violations
  • options.formatter - Formatter name or constructor for output formatting
  • options.formattersDirectory - Directory containing custom formatters
  • options.quiet - Suppress warnings, only show errors
  • options.rulesDirectory - Directory or directories containing custom rules
  • program - Optional TypeScript program for type-aware linting

Instance Methods

lint()

lint(fileName: string, source: string, configuration?: IConfigurationFile): void

Lints a single file with the provided source code and configuration.

Parameters:

  • fileName - File path for error reporting
  • source - Source code to lint
  • configuration - Optional linting configuration (uses default if not provided)

Example:

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

const linter = new Linter({ fix: false });
const config = Configuration.loadConfigurationFromPath('./tslint.json');
const source = fs.readFileSync('./src/example.ts', 'utf8');

linter.lint('./src/example.ts', source, config.results);

getResult()

getResult(): LintResult

Returns the complete linting results after all files have been processed.

interface LintResult {
    errorCount: number;
    warningCount: number;
    failures: RuleFailure[];
    fixes?: RuleFailure[];
    format: string | FormatterConstructor;
    output: string;
}

Example:

const result = linter.getResult();

console.log(`Found ${result.errorCount} errors and ${result.warningCount} warnings`);
console.log('Formatted output:');
console.log(result.output);

// Access individual failures
result.failures.forEach(failure => {
    console.log(`${failure.getFileName()}:${failure.getStartPosition().line + 1} - ${failure.getFailure()}`);
});

Static Properties

class Linter {
    static VERSION: string = "6.1.3";
    static findConfiguration: typeof Configuration.findConfiguration;
    static findConfigurationPath: typeof Configuration.findConfigurationPath;
    static getRulesDirectories: typeof Configuration.getRulesDirectories;
    static loadConfigurationFromPath: typeof Configuration.loadConfigurationFromPath;
}

Static Methods

createProgram()

static createProgram(configFile: string, projectDirectory?: string): ts.Program

Creates a TypeScript program from a tsconfig.json file for type-aware linting.

Parameters:

  • configFile - Path to tsconfig.json file
  • projectDirectory - Optional project root directory

Example:

// Create TypeScript program for type-aware rules
const program = Linter.createProgram('./tsconfig.json', './');
const linter = new Linter({ fix: false }, program);

// Lint files with type information
const fileNames = Linter.getFileNames(program);
fileNames.forEach(fileName => {
    const sourceFile = program.getSourceFile(fileName);
    if (sourceFile) {
        linter.lint(fileName, sourceFile.getFullText(), configuration);
    }
});

getFileNames()

static getFileNames(program: ts.Program): string[]

Extracts lintable file names from a TypeScript program, excluding declaration files.

Configuration Integration

Loading Configuration

import { Configuration, IConfigurationLoadResult } from 'tslint';

// Find configuration relative to a file
const configResult: IConfigurationLoadResult = Configuration.findConfiguration(
    './tslint.json',
    './src/myfile.ts'
);

if (configResult.results) {
    // Use the loaded configuration
    linter.lint('myfile.ts', source, configResult.results);
}

Configuration File Structure

interface IConfigurationFile {
    extends: string[];
    jsRules: Map<string, Partial<IOptions>>;
    linterOptions?: {
        exclude: string[];
        format: string;
    };
    rulesDirectory: string[];
    rules: Map<string, Partial<IOptions>>;
}

Advanced Usage Patterns

Batch Linting Multiple Files

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

function lintProject(pattern: string, configPath: string): LintResult {
    const linter = new Linter({ fix: false, formatter: 'json' });
    const config = Configuration.loadConfigurationFromPath(configPath);
    
    const files = glob.sync(pattern);
    
    files.forEach(filePath => {
        const source = fs.readFileSync(filePath, 'utf8');
        linter.lint(filePath, source, config.results);
    });
    
    return linter.getResult();
}

// Usage
const result = lintProject('./src/**/*.ts', './tslint.json');
console.log(`Project has ${result.errorCount} errors`);

Type-Aware Linting with Program

import { Linter, Configuration } from 'tslint';
import * as ts from 'typescript';

function lintWithTypeChecking(projectPath: string): LintResult {
    // Create TypeScript program
    const program = Linter.createProgram('./tsconfig.json', projectPath);
    const linter = new Linter({ fix: false }, program);
    
    // Load configuration
    const config = Configuration.loadConfigurationFromPath('./tslint.json');
    
    // Get files to lint
    const fileNames = Linter.getFileNames(program);
    
    fileNames.forEach(fileName => {
        const sourceFile = program.getSourceFile(fileName);
        if (sourceFile) {
            linter.lint(fileName, sourceFile.getFullText(), config.results);
        }
    });
    
    return linter.getResult();
}

Auto-fixing with Custom Handling

import { Linter, RuleFailure, Replacement } from 'tslint';
import * as fs from 'fs';

function lintAndFix(filePath: string, config: any): string {
    const source = fs.readFileSync(filePath, 'utf8');
    const linter = new Linter({ fix: true });
    
    linter.lint(filePath, source, config);
    const result = linter.getResult();
    
    // Apply fixes to source code
    if (result.fixes && result.fixes.length > 0) {
        const fixes = result.fixes
            .map(failure => failure.getFix())
            .filter(fix => fix !== undefined) as Replacement[][];
        
        const allReplacements = fixes.reduce((acc, fix) => acc.concat(fix), []);
        return Replacement.applyAll(source, allReplacements);
    }
    
    return source;
}

Custom Formatter Integration

import { Linter, AbstractFormatter } from 'tslint';

class CustomFormatter extends AbstractFormatter {
    public format(failures: RuleFailure[]): string {
        return failures.map(failure => 
            `⚠️  ${failure.getFileName()}: ${failure.getFailure()}`
        ).join('\n');
    }
}

// Use custom formatter
const linter = new Linter({
    fix: false,
    formatter: CustomFormatter
});

Error Handling

import { Linter, Configuration } from 'tslint';

function safeLint(fileName: string, source: string): LintResult | null {
    try {
        const linter = new Linter({ fix: false });
        
        // Attempt to load configuration
        let config;
        try {
            config = Configuration.findConfiguration('./tslint.json', fileName).results;
        } catch (configError) {
            console.warn('Configuration not found, using defaults');
            config = undefined;
        }
        
        linter.lint(fileName, source, config);
        return linter.getResult();
        
    } catch (error) {
        console.error('Linting failed:', error.message);
        return null;
    }
}

Performance Considerations

Reusing TypeScript Program

// Efficient for linting multiple files with type checking
const program = Linter.createProgram('./tsconfig.json');
const linter = new Linter({ fix: false }, program);

// Reuse the same linter and program for multiple files
Linter.getFileNames(program).forEach(fileName => {
    const sourceFile = program.getSourceFile(fileName);
    if (sourceFile) {
        linter.lint(fileName, sourceFile.getFullText(), config);
    }
});

Memory Management

// For large projects, process files in batches
function lintInBatches(files: string[], batchSize: number = 50): LintResult[] {
    const results: LintResult[] = [];
    
    for (let i = 0; i < files.length; i += batchSize) {
        const batch = files.slice(i, i + batchSize);
        const linter = new Linter({ fix: false });
        
        batch.forEach(file => {
            const source = fs.readFileSync(file, 'utf8');
            linter.lint(file, source, config);
        });
        
        results.push(linter.getResult());
    }
    
    return results;
}

Integration Examples

Express.js Middleware

import { Linter, Configuration } from 'tslint';
import * as express from 'express';

function createLintMiddleware() {
    const config = Configuration.loadConfigurationFromPath('./tslint.json');
    
    return (req: express.Request, res: express.Response, next: express.NextFunction) => {
        if (req.body && req.body.source) {
            const linter = new Linter({ fix: false, formatter: 'json' });
            linter.lint('uploaded.ts', req.body.source, config.results);
            
            req.lintResult = linter.getResult();
        }
        next();
    };
}

Build Tool Integration

// Webpack plugin example
class TSLintPlugin {
    apply(compiler: any) {
        compiler.hooks.emit.tapAsync('TSLintPlugin', (compilation: any, callback: Function) => {
            const linter = new Linter({ fix: false });
            const config = Configuration.loadConfigurationFromPath('./tslint.json');
            
            // Lint all TypeScript assets
            Object.keys(compilation.assets).forEach(filename => {
                if (filename.endsWith('.ts')) {
                    const source = compilation.assets[filename].source();
                    linter.lint(filename, source, config.results);
                }
            });
            
            const result = linter.getResult();
            if (result.errorCount > 0) {
                compilation.errors.push(new Error('TSLint errors found'));
            }
            
            callback();
        });
    }
}

Install with Tessl CLI

npx tessl i tessl/npm-tslint

docs

cli.md

configuration.md

formatters.md

index.md

linting.md

rules.md

testing.md

tile.json