npm.io
0.16.6 • Published yesterday

@ttsc/lint

Licence
MIT
Version
0.16.6
Deps
0
Size
2.9 MB
Vulns
0
Weekly
0

@ttsc/lint

banner of @ttsc/lint

GitHub license NPM Version NPM Downloads Build Status Guide Documents Discord Badge

A linter and formatter. Co-protagonist of the ttsc toolchain, paired with ttsc, it replaces eslint and prettier.

720+ rules across 21 families. Lint violations surface as error TSxxxxx from a single compile pass; the formatter applies via ttsc format.

Demonstration

Given this file:

// src/index.ts
var x: number = 3;
let y: number = 4;
const z: string = 5;

console.log(x + y + z);

Run ttsc with @ttsc/lint enabled (see Setup):

$ pnpm ttsc
src/index.ts:3:7 - error TS2322: Type 'number' is not assignable to type 'string'.

3 const z: string = 5;
        ~

src/index.ts:2:5 - error TS17397: [prefer-const] Use const instead of let.

2 let y: number = 4;
      ~~~~~~~~~~~~~

src/index.ts:1:1 - error TS11966: [no-var] Unexpected var, use let or const instead.

1 var x: number = 3;
  ~~~~~~~~~~~~~~~~~~

Found 3 errors in the same file, starting at: src/index.ts:3

Type errors (TS2322) and lint violations (TS17397, TS11966) come out together. No second tool, no second CI step.

Setup

npm install -D ttsc @ttsc/lint typescript@rc

Drop a lint.config.ts next to your tsconfig.json:

// lint.config.ts
import type { ITtscLintConfig } from "@ttsc/lint";

export default {
  format: {
    printWidth: 100,
    singleQuote: true,
    trailingComma: "all",
  },
  rules: {
    "no-var": "error",
    "prefer-const": "error",
    "typescript/no-explicit-any": "error",
    "typescript/no-floating-promises": "error",
  },
} satisfies ITtscLintConfig;

Run your normal ttsc or ttsx:

npx ttsc
npx ttsx src/index.ts

Errors fail the command; warnings print without affecting the exit code. Under ttsx, errors stop the program before your entrypoint runs.

ttsc fix applies every autofix the enabled rules offer, lint and format together. Writes results back to disk, then re-runs type-check + lint. ttsc format runs the format rule set through the same dataflow.

npx ttsc fix
npx ttsc format

ttsc fix is a one-shot project pass and rejects --watch, single-file mode, and --emit. Fixes are written to disk before the recheck runs, so source stays modified even when the command exits non-zero on remaining errors. Recommended flow: run ttsc fix locally, commit, then have CI run ttsc --noEmit to gate on zero remaining errors.

Format

Configure the formatter through the format block in lint.config.ts. Keys mirror .prettierrc; the presence of the block, even empty format: {}, enables the always-on format rules at Prettier defaults so ttsc format rewrites your source to match.

// lint.config.ts
import type { ITtscLintConfig } from "@ttsc/lint";

export default {
  format: {
    printWidth: 100,
    singleQuote: true,
    trailingComma: "all",
    sortImports: {
      order: ["<BUILTIN_MODULES>", "", "<THIRD_PARTY_MODULES>", "", "^[./]"],
    },
    jsDoc: true,
  },
  rules: { "no-var": "error" },
} satisfies ITtscLintConfig;

ttsc check does not fail on formatting by default. It surfaces format diagnostics only when you opt in with format.severity. ttsc format runs the active format rules across the project and writes results to disk regardless of severity.

Each format key controls one behavior:

Config key Effect
severity (default "off") Check-time diagnostic level for formatting. Does not gate ttsc format.
semi Insert trailing semicolons on ASI-terminated statements.
singleQuote Convert quoted strings to the preferred quote style.
arrowParens Add or remove parens around a single arrow parameter.
bracketSpacing Spaces inside object and named-import/export braces.
quoteProps Quote or unquote object property keys.
trailingComma Add trailing commas to multi-line lists.
printWidth, tabWidth, useTabs, endOfLine Column-aware line reflow. Object/array literals, call/new arguments, and named import/export clauses break across lines when their flat form overflows the budget.
sortImports (opt-in) Group imports by order, alphabetize each group + its specifiers, and merge duplicate modules.
jsDoc (on by default) Normalize JSDoc blocks toward prettier-plugin-jsdoc.

sortImports is opt-in — it takes effect only when you set it. Every other key takes effect as soon as the format block is present (JSDoc normalization included; set jsDoc: false to opt out), which also applies several keyless layout behaviors (statement splitting, indentation, whitespace normalization, clause joining, declaration-header reflow, ternary-nullish parens, leading-semicolon merging, and parameter-property breaking).

Formatting is configured only through the format block. The rules map is for lint rules; a format/* id placed there is ignored. To turn a format behavior off, set its format key (for example trailingComma: "none"), not a rules entry.

Rules

Lint rules are off until you enable them in lint.config.ts. Severity values: "error" fails the build, "warning" prints without affecting the exit code, "off" disables the rule.

// lint.config.ts
export default {
  rules: {
    "no-var": "error",
    "eqeqeq": "error",
    "prefer-template": "warning",
    "typescript/no-non-null-assertion": "off",
  },
} satisfies ITtscLintConfig;

Rule IDs use ESLint-style kebab-case and slash namespaces, no-var, react/jsx-key, testing-library/prefer-screen-queries. The exported ITtscLintRules type is the intersection of family-specific interfaces such as ITtscLintCoreRules, ITtscLintTypeScriptRules, ITtscLintReactRules, and ITtscLintVitestRules, so users can type a whole config or a narrower family-shaped object.

Each rule below links to its TypeScript fixture under tests/test-lint/src/cases/.

ESLint core

Generic ESLint-compatible rules that apply to both JavaScript and TypeScript source. Every rule listed here corresponds 1-to-1 with an ESLint core rule of the same kebab-case id, so projects migrating from ESLint can paste their rule severities into lint.config.ts without renaming anything. TypeScript-only rules and @typescript-eslint extensions live under typescript/* in TypeScript, @ttsc/lint does not accept legacy bare names or @typescript-eslint/* aliases for those.

Source: ESLint core rules.

TypeScript

TypeScript-only rules and @typescript-eslint plugin equivalents, exposed under the typescript/* namespace. Each rule either requires TypeScript syntax (interface, enum, namespace, as, !, import type, type parameters, declaration merging, parameter properties, triple-slash references) or originates from @typescript-eslint as a TS-aware extension that has no counterpart in plain ESLint.

Source: typescript-eslint.

React

React TSX rules, Hooks correctness, JSX safety, the React Compiler subset, and Fast Refresh export shape. Bundles rules from three upstream plugins under one react/* namespace, matching Oxlint's layout. Performance-only rules live in React performance because they are opt-in toggles rather than correctness checks.

Source: eslint-plugin-react, eslint-plugin-react-hooks, eslint-plugin-react-refresh.

Keywords