# How to Use createDiagnosticsPlugin in tsslint to Filter and Modify TypeScript Diagnostics

> Learn how to use createDiagnosticsPlugin in tsslint to filter and modify TypeScript diagnostics. Unified error handling for better code quality.

- Repository: [Johnson Chu/tsslint](https://github.com/johnsoncodehk/tsslint)
- Tags: how-to-guide
- Published: 2026-03-04

---

**The `createDiagnosticsPlugin` is a built-in tsslint factory function that collects TypeScript compiler diagnostics (syntactic, semantic, or declaration errors) and merges them with lint rule diagnostics, enabling unified filtering, enrichment, or transformation of the final diagnostic output.**

The `createDiagnosticsPlugin` serves as a bridge between TypeScript's native error detection and tsslint's rule-based linting system. Implemented in [`packages/config/lib/plugins/diagnostics.ts`](https://github.com/johnsoncodehk/tsslint/blob/main/packages/config/lib/plugins/diagnostics.ts) and exported from `@tsslint/config`, this plugin implements the `PluginInstance` interface to intercept and augment the diagnostic stream before final reporting.

## What createDiagnosticsPlugin Does

The primary purpose of `createDiagnosticsPlugin` is to inject TypeScript compiler diagnostics into the linting results. According to the implementation in [`packages/config/lib/plugins/diagnostics.ts`](https://github.com/johnsoncodehk/tsslint/blob/main/packages/config/lib/plugins/diagnostics.ts), the plugin performs three core operations:

- **Collects TypeScript diagnostics** – Retrieves diagnostics from the TypeScript program based on the specified check mode(s): `'syntactic'`, `'semantic'`, or `'declaration'`.
- **Merges with lint diagnostics** – Appends the collected TypeScript diagnostics to the array of diagnostics produced by tsslint rules.
- **Normalizes missing fields** – Ensures every diagnostic has defined `start` and `length` properties, defaulting to `0` if undefined, preventing downstream errors in formatters or other plugins.

## How createDiagnosticsPlugin Fits into the Architecture

Understanding the plugin's position in tsslint's execution flow clarifies how to leverage it effectively for filtering and modification.

### Plugin Interface Implementation

All tsslint plugins implement the `PluginInstance` interface defined in [`packages/types/index.ts`](https://github.com/johnsoncodehk/tsslint/blob/main/packages/types/index.ts). The relevant hook is the optional `resolveDiagnostics?` method:

```typescript
// packages/types/index.ts
interface PluginInstance {
  resolveDiagnostics?(fileName: string, diagnostics: Diagnostic[]): Diagnostic[];
  // ... other methods
}

```

The `createDiagnosticsPlugin` returns an object implementing this interface, specifically providing the `resolveDiagnostics` function that modifies the diagnostics array.

### Core Runner Integration

The tsslint core runner invokes plugin hooks in [`packages/core/index.ts`](https://github.com/johnsoncodehk/tsslint/blob/main/packages/core/index.ts) (lines 167-173). After executing lint rules, the runner calls each plugin's `resolveDiagnostics` method in sequence, passing the accumulated diagnostics array. This allows `createDiagnosticsPlugin` to augment the diagnostics before they reach the formatter or output stage.

### Export Location

The factory function is exported from [`packages/config/index.ts`](https://github.com/johnsoncodehk/tsslint/blob/main/packages/config/index.ts) as `createDiagnosticsPlugin`, making it available via the `@tsslint/config` package:

```typescript
// packages/config/index.ts
export { createDiagnosticsPlugin } from './lib/plugins/diagnostics';

```

## Configuration and Usage Examples

### Basic Usage: Adding Semantic Diagnostics

By default, `createDiagnosticsPlugin()` collects **semantic** diagnostics from TypeScript. This is the most common use case for catching type errors alongside lint violations.

```typescript
// tsslint.config.ts
import { defineConfig, createDiagnosticsPlugin } from '@tsslint/config';
import NoConsoleRule from './noConsoleRule';

export default defineConfig({
  rules: {
    'no-console': NoConsoleRule,
  },
  plugins: [
    // Inject TypeScript semantic diagnostics into the lint report
    createDiagnosticsPlugin(),
  ],
});

```

The factory signature confirms this default: `create(mode: CheckMode | CheckMode[] = 'semantic')`.

### Requesting Multiple Diagnostic Kinds

To capture syntactic errors (parse errors) alongside semantic ones, pass an array of check modes:

```typescript
// tsslint.config.ts
import { defineConfig, createDiagnosticsPlugin } from '@tsslint/config';

export default defineConfig({
  plugins: [
    // Collect both syntactic and semantic diagnostics
    createDiagnosticsPlugin(['syntactic', 'semantic']),
  ],
});

```

Available modes include:
- `'syntactic'` – Parse errors and malformed syntax
- `'semantic'` – Type checking errors
- `'declaration'` – Errors in declaration files ([`.d.ts`](https://github.com/johnsoncodehk/tsslint/blob/main/.d.ts))

### Chaining with Diagnostic Filter Plugins

Because tsslint processes plugins sequentially, you can chain `createDiagnosticsPlugin` with other plugins to filter or modify the merged output. For example, combining with an ignore plugin:

```typescript
// tsslint.config.ts
import { defineConfig, createDiagnosticsPlugin, createIgnorePlugin } from '@tsslint/config';

export default defineConfig({
  plugins: [
    // First: Add TypeScript diagnostics to the array
    createDiagnosticsPlugin(),
    // Then: Remove diagnostics on lines containing // @tsslint-ignore
    createIgnorePlugin(/\/\/ @tsslint-ignore/g),
  ],
});

```

The order matters: the ignore plugin receives the augmented diagnostics array including the TypeScript compiler errors, allowing it to filter both rule violations and compiler diagnostics.

### Advanced: Programmatic Usage

For custom tooling or testing, you can invoke the plugin factory directly without the config file abstraction:

```typescript
import { createDiagnosticsPlugin } from '@tsslint/config';
import { createProgram } from 'typescript';

// Setup TypeScript program
const program = createProgram(['src/index.ts'], {});
const sourceFile = program.getSourceFile('src/index.ts')!;

// Initial diagnostics array (possibly from other rules)
let diagnostics: ts.DiagnosticWithLocation[] = [];

// Create plugin instance with specific modes
const plugin = createDiagnosticsPlugin(['semantic', 'declaration'])({
  languageService: { getProgram: () => program } as any,
});

// Resolve diagnostics
if (plugin.resolveDiagnostics) {
  diagnostics = plugin.resolveDiagnostics(sourceFile.fileName, diagnostics);
}

```

This demonstrates the low-level contract: the plugin receives a `languageService` with a `getProgram` method and returns an object with a `resolveDiagnostics` function that transforms the array.

## Summary

- **Purpose**: `createDiagnosticsPlugin` bridges TypeScript compiler diagnostics and tsslint rule diagnostics, enabling unified error reporting.
- **Location**: Implemented in [`packages/config/lib/plugins/diagnostics.ts`](https://github.com/johnsoncodehk/tsslint/blob/main/packages/config/lib/plugins/diagnostics.ts) and exported from [`packages/config/index.ts`](https://github.com/johnsoncodehk/tsslint/blob/main/packages/config/index.ts).
- **Default behavior**: Collects semantic diagnostics unless configured otherwise with `'syntactic'`, `'semantic'`, or `'declaration'` modes.
- **Integration**: Implements the `PluginInstance` interface from [`packages/types/index.ts`](https://github.com/johnsoncodehk/tsslint/blob/main/packages/types/index.ts), specifically the `resolveDiagnostics?` hook called by the core runner in [`packages/core/index.ts`](https://github.com/johnsoncodehk/tsslint/blob/main/packages/core/index.ts).
- **Normalization**: Automatically ensures all diagnostics have `start` and `length` properties set to `0` if undefined.
- **Chaining**: Works sequentially with other plugins, allowing filtering or modification of the merged diagnostic array based on plugin order.

## Frequently Asked Questions

### What is the default diagnostic mode for createDiagnosticsPlugin?

By default, `createDiagnosticsPlugin()` operates in `'semantic'` mode. This means it collects only semantic diagnostics from the TypeScript program (type errors), ignoring syntactic parse errors and declaration file diagnostics unless explicitly requested via the configuration array.

### How does createDiagnosticsPlugin handle diagnostics without position information?

The plugin normalizes diagnostics to ensure downstream compatibility. In [`packages/config/lib/plugins/diagnostics.ts`](https://github.com/johnsoncodehk/tsslint/blob/main/packages/config/lib/plugins/diagnostics.ts), the implementation checks for undefined `start` and `length` properties on each diagnostic and defaults them to `0`. This prevents errors in formatters or other plugins that expect these numeric fields to be defined.

### Can I use createDiagnosticsPlugin with custom tsslint rules?

Yes. The plugin is designed to merge with existing diagnostics rather than replace them. When the core runner in [`packages/core/index.ts`](https://github.com/johnsoncodehk/tsslint/blob/main/packages/core/index.ts) invokes `resolveDiagnostics`, it passes the array of diagnostics already produced by your custom rules. The plugin appends TypeScript compiler diagnostics to this array, creating a unified report containing both rule violations and compiler errors.

### Where should createDiagnosticsPlugin appear in the plugins array order?

Position depends on your filtering needs. If you want to filter or modify TypeScript diagnostics (for example, ignoring certain compiler errors), place `createDiagnosticsPlugin` **before** filter plugins like `createIgnorePlugin`. If you want to ensure your ignore rules also apply to TypeScript diagnostics, place it **before** the ignore plugin so the filter receives the merged array. The core runner processes plugins sequentially in [`packages/core/index.ts`](https://github.com/johnsoncodehk/tsslint/blob/main/packages/core/index.ts), so order determines which transformations see which diagnostics.