0
# Core Linting
1
2
This document covers TSLint's core linting functionality, including the Linter class, programmatic usage patterns, and integration with TypeScript programs.
3
4
## Linter Class
5
6
The `Linter` class is TSLint's primary interface for programmatic linting operations.
7
8
### Constructor
9
10
```typescript { .api }
11
class Linter {
12
constructor(options: ILinterOptions, program?: ts.Program)
13
}
14
```
15
16
```typescript { .api }
17
interface ILinterOptions {
18
fix: boolean;
19
formatter?: string | FormatterConstructor;
20
formattersDirectory?: string;
21
quiet?: boolean;
22
rulesDirectory?: string | string[];
23
}
24
```
25
26
**Parameters:**
27
- `options.fix` - Enable automatic fixing of violations
28
- `options.formatter` - Formatter name or constructor for output formatting
29
- `options.formattersDirectory` - Directory containing custom formatters
30
- `options.quiet` - Suppress warnings, only show errors
31
- `options.rulesDirectory` - Directory or directories containing custom rules
32
- `program` - Optional TypeScript program for type-aware linting
33
34
### Instance Methods
35
36
#### lint()
37
38
```typescript { .api }
39
lint(fileName: string, source: string, configuration?: IConfigurationFile): void
40
```
41
42
Lints a single file with the provided source code and configuration.
43
44
**Parameters:**
45
- `fileName` - File path for error reporting
46
- `source` - Source code to lint
47
- `configuration` - Optional linting configuration (uses default if not provided)
48
49
**Example:**
50
```typescript
51
import { Linter, Configuration } from 'tslint';
52
import * as fs from 'fs';
53
54
const linter = new Linter({ fix: false });
55
const config = Configuration.loadConfigurationFromPath('./tslint.json');
56
const source = fs.readFileSync('./src/example.ts', 'utf8');
57
58
linter.lint('./src/example.ts', source, config.results);
59
```
60
61
#### getResult()
62
63
```typescript { .api }
64
getResult(): LintResult
65
```
66
67
Returns the complete linting results after all files have been processed.
68
69
```typescript { .api }
70
interface LintResult {
71
errorCount: number;
72
warningCount: number;
73
failures: RuleFailure[];
74
fixes?: RuleFailure[];
75
format: string | FormatterConstructor;
76
output: string;
77
}
78
```
79
80
**Example:**
81
```typescript
82
const result = linter.getResult();
83
84
console.log(`Found ${result.errorCount} errors and ${result.warningCount} warnings`);
85
console.log('Formatted output:');
86
console.log(result.output);
87
88
// Access individual failures
89
result.failures.forEach(failure => {
90
console.log(`${failure.getFileName()}:${failure.getStartPosition().line + 1} - ${failure.getFailure()}`);
91
});
92
```
93
94
### Static Properties
95
96
```typescript { .api }
97
class Linter {
98
static VERSION: string = "6.1.3";
99
static findConfiguration: typeof Configuration.findConfiguration;
100
static findConfigurationPath: typeof Configuration.findConfigurationPath;
101
static getRulesDirectories: typeof Configuration.getRulesDirectories;
102
static loadConfigurationFromPath: typeof Configuration.loadConfigurationFromPath;
103
}
104
```
105
106
### Static Methods
107
108
#### createProgram()
109
110
```typescript { .api }
111
static createProgram(configFile: string, projectDirectory?: string): ts.Program
112
```
113
114
Creates a TypeScript program from a tsconfig.json file for type-aware linting.
115
116
**Parameters:**
117
- `configFile` - Path to tsconfig.json file
118
- `projectDirectory` - Optional project root directory
119
120
**Example:**
121
```typescript
122
// Create TypeScript program for type-aware rules
123
const program = Linter.createProgram('./tsconfig.json', './');
124
const linter = new Linter({ fix: false }, program);
125
126
// Lint files with type information
127
const fileNames = Linter.getFileNames(program);
128
fileNames.forEach(fileName => {
129
const sourceFile = program.getSourceFile(fileName);
130
if (sourceFile) {
131
linter.lint(fileName, sourceFile.getFullText(), configuration);
132
}
133
});
134
```
135
136
#### getFileNames()
137
138
```typescript { .api }
139
static getFileNames(program: ts.Program): string[]
140
```
141
142
Extracts lintable file names from a TypeScript program, excluding declaration files.
143
144
## Configuration Integration
145
146
### Loading Configuration
147
148
```typescript
149
import { Configuration, IConfigurationLoadResult } from 'tslint';
150
151
// Find configuration relative to a file
152
const configResult: IConfigurationLoadResult = Configuration.findConfiguration(
153
'./tslint.json',
154
'./src/myfile.ts'
155
);
156
157
if (configResult.results) {
158
// Use the loaded configuration
159
linter.lint('myfile.ts', source, configResult.results);
160
}
161
```
162
163
### Configuration File Structure
164
165
```typescript { .api }
166
interface IConfigurationFile {
167
extends: string[];
168
jsRules: Map<string, Partial<IOptions>>;
169
linterOptions?: {
170
exclude: string[];
171
format: string;
172
};
173
rulesDirectory: string[];
174
rules: Map<string, Partial<IOptions>>;
175
}
176
```
177
178
## Advanced Usage Patterns
179
180
### Batch Linting Multiple Files
181
182
```typescript
183
import { Linter, Configuration } from 'tslint';
184
import * as fs from 'fs';
185
import * as glob from 'glob';
186
187
function lintProject(pattern: string, configPath: string): LintResult {
188
const linter = new Linter({ fix: false, formatter: 'json' });
189
const config = Configuration.loadConfigurationFromPath(configPath);
190
191
const files = glob.sync(pattern);
192
193
files.forEach(filePath => {
194
const source = fs.readFileSync(filePath, 'utf8');
195
linter.lint(filePath, source, config.results);
196
});
197
198
return linter.getResult();
199
}
200
201
// Usage
202
const result = lintProject('./src/**/*.ts', './tslint.json');
203
console.log(`Project has ${result.errorCount} errors`);
204
```
205
206
### Type-Aware Linting with Program
207
208
```typescript
209
import { Linter, Configuration } from 'tslint';
210
import * as ts from 'typescript';
211
212
function lintWithTypeChecking(projectPath: string): LintResult {
213
// Create TypeScript program
214
const program = Linter.createProgram('./tsconfig.json', projectPath);
215
const linter = new Linter({ fix: false }, program);
216
217
// Load configuration
218
const config = Configuration.loadConfigurationFromPath('./tslint.json');
219
220
// Get files to lint
221
const fileNames = Linter.getFileNames(program);
222
223
fileNames.forEach(fileName => {
224
const sourceFile = program.getSourceFile(fileName);
225
if (sourceFile) {
226
linter.lint(fileName, sourceFile.getFullText(), config.results);
227
}
228
});
229
230
return linter.getResult();
231
}
232
```
233
234
### Auto-fixing with Custom Handling
235
236
```typescript
237
import { Linter, RuleFailure, Replacement } from 'tslint';
238
import * as fs from 'fs';
239
240
function lintAndFix(filePath: string, config: any): string {
241
const source = fs.readFileSync(filePath, 'utf8');
242
const linter = new Linter({ fix: true });
243
244
linter.lint(filePath, source, config);
245
const result = linter.getResult();
246
247
// Apply fixes to source code
248
if (result.fixes && result.fixes.length > 0) {
249
const fixes = result.fixes
250
.map(failure => failure.getFix())
251
.filter(fix => fix !== undefined) as Replacement[][];
252
253
const allReplacements = fixes.reduce((acc, fix) => acc.concat(fix), []);
254
return Replacement.applyAll(source, allReplacements);
255
}
256
257
return source;
258
}
259
```
260
261
### Custom Formatter Integration
262
263
```typescript
264
import { Linter, AbstractFormatter } from 'tslint';
265
266
class CustomFormatter extends AbstractFormatter {
267
public format(failures: RuleFailure[]): string {
268
return failures.map(failure =>
269
`⚠️ ${failure.getFileName()}: ${failure.getFailure()}`
270
).join('\n');
271
}
272
}
273
274
// Use custom formatter
275
const linter = new Linter({
276
fix: false,
277
formatter: CustomFormatter
278
});
279
```
280
281
## Error Handling
282
283
```typescript
284
import { Linter, Configuration } from 'tslint';
285
286
function safeLint(fileName: string, source: string): LintResult | null {
287
try {
288
const linter = new Linter({ fix: false });
289
290
// Attempt to load configuration
291
let config;
292
try {
293
config = Configuration.findConfiguration('./tslint.json', fileName).results;
294
} catch (configError) {
295
console.warn('Configuration not found, using defaults');
296
config = undefined;
297
}
298
299
linter.lint(fileName, source, config);
300
return linter.getResult();
301
302
} catch (error) {
303
console.error('Linting failed:', error.message);
304
return null;
305
}
306
}
307
```
308
309
## Performance Considerations
310
311
### Reusing TypeScript Program
312
313
```typescript
314
// Efficient for linting multiple files with type checking
315
const program = Linter.createProgram('./tsconfig.json');
316
const linter = new Linter({ fix: false }, program);
317
318
// Reuse the same linter and program for multiple files
319
Linter.getFileNames(program).forEach(fileName => {
320
const sourceFile = program.getSourceFile(fileName);
321
if (sourceFile) {
322
linter.lint(fileName, sourceFile.getFullText(), config);
323
}
324
});
325
```
326
327
### Memory Management
328
329
```typescript
330
// For large projects, process files in batches
331
function lintInBatches(files: string[], batchSize: number = 50): LintResult[] {
332
const results: LintResult[] = [];
333
334
for (let i = 0; i < files.length; i += batchSize) {
335
const batch = files.slice(i, i + batchSize);
336
const linter = new Linter({ fix: false });
337
338
batch.forEach(file => {
339
const source = fs.readFileSync(file, 'utf8');
340
linter.lint(file, source, config);
341
});
342
343
results.push(linter.getResult());
344
}
345
346
return results;
347
}
348
```
349
350
## Integration Examples
351
352
### Express.js Middleware
353
354
```typescript
355
import { Linter, Configuration } from 'tslint';
356
import * as express from 'express';
357
358
function createLintMiddleware() {
359
const config = Configuration.loadConfigurationFromPath('./tslint.json');
360
361
return (req: express.Request, res: express.Response, next: express.NextFunction) => {
362
if (req.body && req.body.source) {
363
const linter = new Linter({ fix: false, formatter: 'json' });
364
linter.lint('uploaded.ts', req.body.source, config.results);
365
366
req.lintResult = linter.getResult();
367
}
368
next();
369
};
370
}
371
```
372
373
### Build Tool Integration
374
375
```typescript
376
// Webpack plugin example
377
class TSLintPlugin {
378
apply(compiler: any) {
379
compiler.hooks.emit.tapAsync('TSLintPlugin', (compilation: any, callback: Function) => {
380
const linter = new Linter({ fix: false });
381
const config = Configuration.loadConfigurationFromPath('./tslint.json');
382
383
// Lint all TypeScript assets
384
Object.keys(compilation.assets).forEach(filename => {
385
if (filename.endsWith('.ts')) {
386
const source = compilation.assets[filename].source();
387
linter.lint(filename, source, config.results);
388
}
389
});
390
391
const result = linter.getResult();
392
if (result.errorCount > 0) {
393
compilation.errors.push(new Error('TSLint errors found'));
394
}
395
396
callback();
397
});
398
}
399
}
400
```