0
# Programmatic API
1
2
The type-coverage-core library provides a programmatic API for integrating TypeScript type coverage analysis into custom tools, build systems, and development workflows.
3
4
## Capabilities
5
6
### Primary Analysis Functions
7
8
#### Asynchronous Type Coverage Analysis
9
10
Analyze a TypeScript project asynchronously with automatic configuration discovery.
11
12
```typescript { .api }
13
/**
14
* Analyze TypeScript project for type coverage
15
* @param project - Path to project directory or tsconfig.json file
16
* @param options - Optional configuration for analysis
17
* @returns Promise resolving to analysis results
18
*/
19
function lint(
20
project: string,
21
options?: Partial<LintOptions>
22
): Promise<LintResult>;
23
```
24
25
**Usage Examples:**
26
27
```typescript
28
import { lint } from "type-coverage-core";
29
30
// Basic analysis
31
const result = await lint("./");
32
console.log(`Coverage: ${result.correctCount}/${result.totalCount}`);
33
34
// Analysis with options
35
const result = await lint("./src", {
36
strict: true,
37
enableCache: true,
38
ignoreFiles: ["**/*.test.ts"],
39
reportSemanticError: true
40
});
41
42
// Check coverage threshold
43
const percentage = (result.correctCount / result.totalCount) * 100;
44
if (percentage < 90) {
45
throw new Error(`Coverage ${percentage.toFixed(2)}% below threshold`);
46
}
47
```
48
49
#### Synchronous Type Coverage Analysis
50
51
Analyze TypeScript files synchronously with explicit compiler configuration.
52
53
```typescript { .api }
54
/**
55
* Analyze TypeScript files synchronously with explicit configuration
56
* @param compilerOptions - TypeScript compiler options
57
* @param rootNames - Array of root file paths to analyze
58
* @param options - Optional configuration for analysis
59
* @returns Analysis results
60
*/
61
function lintSync(
62
compilerOptions: ts.CompilerOptions,
63
rootNames: string[],
64
options?: Partial<LintOptions>
65
): LintSyncResult;
66
```
67
68
**Usage Examples:**
69
70
```typescript
71
import { lintSync } from "type-coverage-core";
72
import * as ts from "typescript";
73
74
// With explicit configuration
75
const compilerOptions: ts.CompilerOptions = {
76
target: ts.ScriptTarget.ES2020,
77
module: ts.ModuleKind.CommonJS,
78
lib: ["ES2020"],
79
strict: true
80
};
81
82
const result = lintSync(compilerOptions, ["src/main.ts", "src/utils.ts"], {
83
strict: true,
84
ignoreNested: true
85
});
86
87
console.log(`Files analyzed: ${result.fileCounts?.size || 0}`);
88
```
89
90
## Types and Interfaces
91
92
### Analysis Results
93
94
```typescript { .api }
95
// Return type for lint() function
96
type LintResult = {
97
/** Number of identifiers with explicit types */
98
correctCount: number;
99
/** Total number of identifiers analyzed */
100
totalCount: number;
101
/** Array of any type issues found */
102
anys: AnyInfo[];
103
/** TypeScript program instance used for analysis */
104
program: ts.Program;
105
/** Per-file coverage statistics (when fileCounts option is true) */
106
fileCounts: Map<string, Pick<FileTypeCheckResult, 'correctCount' | 'totalCount'>>;
107
};
108
109
// Return type for lintSync() function
110
type LintSyncResult = {
111
/** Number of identifiers with explicit types */
112
correctCount: number;
113
/** Total number of identifiers analyzed */
114
totalCount: number;
115
/** Array of any type issues with source file references */
116
anys: Array<AnyInfo & { sourceFile: ts.SourceFile }>;
117
/** TypeScript program instance used for analysis */
118
program: ts.Program;
119
/** Per-file coverage statistics (when fileCounts option is true) */
120
fileCounts: Map<string, Pick<FileTypeCheckResult, 'correctCount' | 'totalCount'>>;
121
};
122
```
123
124
### Configuration Options
125
126
```typescript { .api }
127
interface LintOptions {
128
/** Enable debug output during analysis */
129
debug: boolean;
130
/** Enable strict mode checking (includes all strict options) */
131
strict: boolean;
132
/** Enable result caching for improved performance */
133
enableCache: boolean;
134
/** File patterns to ignore during analysis */
135
ignoreFiles?: string | string[];
136
/** Ignore catch clause variables */
137
ignoreCatch: boolean;
138
/** Allow writes to variables with implicit any types */
139
ignoreUnreadAnys: boolean;
140
/** Generate per-file coverage statistics */
141
fileCounts: boolean;
142
/** Use absolute file paths in results */
143
absolutePath?: boolean;
144
/** Report TypeScript semantic errors */
145
reportSemanticError: boolean;
146
/** Report unused ignore directives */
147
reportUnusedIgnore: boolean;
148
/** Custom cache directory location */
149
cacheDirectory?: string;
150
/** Include results outside current working directory */
151
notOnlyInCWD?: boolean;
152
/** Specific files to analyze (overrides project discovery) */
153
files?: string[];
154
/** Previous TypeScript program for incremental compilation */
155
oldProgram?: ts.Program;
156
/** Custom any type processor function */
157
processAny?: ProccessAny;
158
159
// Strict mode options (individually configurable)
160
/** Ignore any in type arguments (Promise<any>) */
161
ignoreNested: boolean;
162
/** Ignore as assertions (foo as string) */
163
ignoreAsAssertion: boolean;
164
/** Ignore type assertions (<string>foo) */
165
ignoreTypeAssertion: boolean;
166
/** Ignore non-null assertions (foo!) */
167
ignoreNonNullAssertion: boolean;
168
/** Don't count Object type as any */
169
ignoreObject: boolean;
170
/** Don't count empty type {} as any */
171
ignoreEmptyType: boolean;
172
}
173
```
174
175
### Issue Information
176
177
```typescript { .api }
178
interface AnyInfo {
179
/** File path where issue was found */
180
file: string;
181
/** Line number (0-based) */
182
line: number;
183
/** Character position (0-based) */
184
character: number;
185
/** Description of the issue */
186
text: string;
187
/** Category of any type issue */
188
kind: FileAnyInfoKind;
189
}
190
191
interface FileAnyInfo {
192
/** Line number (0-based) */
193
line: number;
194
/** Character position (0-based) */
195
character: number;
196
/** Description of the issue */
197
text: string;
198
/** Category of any type issue */
199
kind: FileAnyInfoKind;
200
}
201
202
enum FileAnyInfoKind {
203
/** Explicit any type */
204
any = 1,
205
/** any in type arguments (Promise<any>) */
206
containsAny = 2,
207
/** Unsafe as assertion (foo as string) */
208
unsafeAs = 3,
209
/** Unsafe type assertion (<string>foo) */
210
unsafeTypeAssertion = 4,
211
/** Unsafe non-null assertion (foo!) */
212
unsafeNonNull = 5,
213
/** TypeScript semantic error */
214
semanticError = 6,
215
/** Unused ignore directive */
216
unusedIgnore = 7
217
}
218
```
219
220
### File Analysis Results
221
222
```typescript { .api }
223
interface FileTypeCheckResult {
224
/** Number of identifiers with explicit types in this file */
225
correctCount: number;
226
/** Total number of identifiers in this file */
227
totalCount: number;
228
/** Array of any type issues in this file */
229
anys: FileAnyInfo[];
230
}
231
```
232
233
### Custom Processing
234
235
```typescript { .api }
236
/**
237
* Custom processor function for any type nodes
238
* @param node - TypeScript AST node being processed
239
* @param context - File analysis context
240
* @returns true if node should be counted as any type issue
241
*/
242
type ProccessAny = (node: ts.Node, context: FileContext) => boolean;
243
244
interface FileContext {
245
/** Current file path */
246
file: string;
247
/** TypeScript source file */
248
sourceFile: ts.SourceFile;
249
/** Type checker instance */
250
checker: ts.TypeChecker;
251
/** Current analysis results */
252
typeCheckResult: FileTypeCheckResult;
253
/** Catch clause variables (for ignoreCatch option) */
254
catchVariables: { [variable: string]: boolean };
255
/** Lines with ignore directives */
256
ignoreLines?: Set<number>;
257
/** Lines where ignore directives were used */
258
usedIgnoreLines?: Set<number>;
259
260
// Configuration options
261
debug: boolean;
262
strict: boolean;
263
ignoreCatch: boolean;
264
ignoreUnreadAnys: boolean;
265
ignoreNested: boolean;
266
ignoreAsAssertion: boolean;
267
ignoreTypeAssertion: boolean;
268
ignoreNonNullAssertion: boolean;
269
ignoreObject: boolean;
270
ignoreEmptyType: boolean;
271
processAny?: ProccessAny;
272
}
273
```
274
275
## Advanced Usage Examples
276
277
### Custom Analysis Pipeline
278
279
```typescript
280
import { lint, FileAnyInfoKind } from "type-coverage-core";
281
282
async function analyzeProject(projectPath: string) {
283
const result = await lint(projectPath, {
284
strict: true,
285
enableCache: true,
286
fileCounts: true,
287
reportSemanticError: true
288
});
289
290
// Calculate overall coverage
291
const coverage = (result.correctCount / result.totalCount) * 100;
292
293
// Group issues by type
294
const issuesByKind = result.anys.reduce((acc, issue) => {
295
const kind = FileAnyInfoKind[issue.kind];
296
acc[kind] = (acc[kind] || 0) + 1;
297
return acc;
298
}, {} as Record<string, number>);
299
300
// Analyze per-file coverage
301
const fileStats = Array.from(result.fileCounts?.entries() || [])
302
.map(([file, stats]) => ({
303
file,
304
coverage: (stats.correctCount / stats.totalCount) * 100,
305
issues: stats.anys.length
306
}))
307
.sort((a, b) => a.coverage - b.coverage);
308
309
return {
310
overall: { coverage, issues: result.anys.length },
311
byType: issuesByKind,
312
byFile: fileStats
313
};
314
}
315
```
316
317
### Integration with Build Tools
318
319
```typescript
320
import { lint } from "type-coverage-core";
321
322
async function typeCoveragePlugin(options: { threshold: number }) {
323
return {
324
name: "type-coverage",
325
async buildStart() {
326
const result = await lint("./", {
327
strict: true,
328
enableCache: true
329
});
330
331
const coverage = (result.correctCount / result.totalCount) * 100;
332
333
if (coverage < options.threshold) {
334
this.error(
335
`Type coverage ${coverage.toFixed(2)}% below threshold ${options.threshold}%`
336
);
337
}
338
339
console.log(`Type coverage: ${coverage.toFixed(2)}%`);
340
}
341
};
342
}
343
```
344
345
### Incremental Analysis
346
347
```typescript
348
import { lintSync } from "type-coverage-core";
349
import * as ts from "typescript";
350
351
class IncrementalTypeCoverage {
352
private program: ts.Program | undefined;
353
354
async analyze(compilerOptions: ts.CompilerOptions, rootNames: string[]) {
355
const result = lintSync(compilerOptions, rootNames, {
356
oldProgram: this.program,
357
enableCache: true,
358
fileCounts: true
359
});
360
361
// Store program for next incremental analysis
362
this.program = result.program;
363
364
return result;
365
}
366
}
367
```