Skip to content

base

npm version License: MIT Node.js

> Base Oxlint configuration for JavaScript and TypeScript. Ports @jmlweb/eslint-config-base-js and @jmlweb/eslint-config-base to a linter that runs in milliseconds. Recommended linter.

  • ⚡ Fast: Oxlint is written in Rust; type-aware rules run on the Go port of TypeScript
  • 🔒 Strict TypeScript: typescript-eslint recommended, strict-type-checked and stylistic-type-checked rules
  • 🟨 JavaScript and TypeScript in one config: ESLint recommended rules everywhere, TypeScript rules for .ts/.tsx/.mts/.cts
  • 🎯 Same conventions: type over interface, no enums, no any, named exports only, no parameter mutation
Terminal window
npm install --save-dev @jmlweb/oxlint-config-base oxlint oxlint-tsgolint

> oxlint-tsgolint is only needed for type-aware rules.

Create oxlint.config.ts in your project root:

import baseConfig from '@jmlweb/oxlint-config-base';
import { defineConfig } from 'oxlint';
export default defineConfig({
extends: [baseConfig],
options: {
typeAware: true,
},
});

> ⚠️ Set typeAware in your own config. Oxlint reads options only from the root config, not from configs loaded through extends. Without it, type-aware rules are skipped silently.

enum Status {
Active,
}
interface User {
name: string;
}
export default function rename(user: User, data: any) {
user.name = data.name;
save(user);
}
src/user.ts:1:1: error jmlweb(no-enum): Use const maps instead of enums
src/user.ts:1:6: error eslint(no-unused-vars): Enum 'Status' is declared but never used.
src/user.ts:5:1: error typescript(consistent-type-definitions): Use `type` instead of `interface`.
src/user.ts:9:8: error import(no-default-export): Prefer named exports
src/user.ts:9:50: error typescript(no-explicit-any): Unexpected `any`. Specify a different type.
src/user.ts:10:3: error eslint(no-param-reassign): Assignment to property of function parameter 'user'.
src/user.ts:10:15: error typescript(no-unsafe-assignment): Unsafe assignment of an any value.
src/user.ts:10:20: error typescript(no-unsafe-member-access): Unsafe member access .name on an `any` value.
src/user.ts:11:3: error typescript(no-floating-promises): Promises must be awaited, add void operator to ignore.
const STATUS = { ACTIVE: 'active' } as const;
type User = {
name: string;
};
export const rename = async (user: User, name: string): Promise<User> => {
const renamed = { ...user, name };
await save(renamed);
return renamed;
};

All files: Oxlint’s correctness category as error, plus Oxlint equivalents of ESLint’s recommended rules.

TypeScript files (**/*.{ts,tsx,mts,cts}):

  • typescript-eslint recommended, strict and stylistic rules
  • typescript-eslint strict-type-checked and stylistic-type-checked rules (with options.typeAware)
  • Core rules the TypeScript compiler already checks (such as no-undef) turned off
Rule Level Description
typescript/no-explicit-any error No any
typescript/consistent-type-imports error Inline type imports
typescript/consistent-type-definitions error type over interface
jmlweb/no-enum error No enums (use const maps)
import/no-default-export error Named exports only
eslint/no-param-reassign error No mutating parameters or their props
eslint/no-unused-vars error Names prefixed with _ are allowed

**/*.config.{ts,mts,cts} files may use default exports, since tools require them.

jmlweb/no-enum is a bundled JS plugin (@jmlweb/oxlint-config-base/plugin), because Oxlint has no no-restricted-syntax. Oxlint’s JS plugin support is still in alpha.

Differences from @jmlweb/eslint-config-base

Section titled “Differences from @jmlweb/eslint-config-base”
  • No naming-convention: needs typescript-eslint’s parser, which Oxlint cannot run
  • No import sorting: @jmlweb/oxfmt-config-base sorts imports when formatting
  • No Prettier conflict rules: this config enables no formatting rules
  • No no-unsafe-enum-assignment: not available in Oxlint, and enums are banned anyway
  • ✅ Fast linting for new JavaScript or TypeScript projects (recommended)
  • ✅ Migrating from @jmlweb/eslint-config-base or @jmlweb/eslint-config-base-js (maintenance mode)
  • ✅ Type-aware rules without typescript-eslint’s runtime cost

React: use @jmlweb/oxlint-config-react. Node.js: use @jmlweb/oxlint-config-node. Astro: keep @jmlweb/eslint-config-astro; Oxlint cannot lint .astro templates.

import baseConfig from '@jmlweb/oxlint-config-base';
import { defineConfig } from 'oxlint';
export default defineConfig({
extends: [baseConfig],
options: {
typeAware: true,
},
env: {
node: true,
},
ignorePatterns: ['generated/**'],
rules: {
'jmlweb/no-enum': 'off',
},
overrides: [
{
files: ['**/*.test.ts'],
rules: {
'typescript/no-non-null-assertion': 'off',
},
},
],
});

To keep eslint-plugin-simple-import-sort’s order, set sortImports: false in your Oxfmt config and run the plugin through Oxlint:

import baseConfig from '@jmlweb/oxlint-config-base';
import { defineConfig } from 'oxlint';
export default defineConfig({
extends: [baseConfig],
jsPlugins: ['eslint-plugin-simple-import-sort'],
rules: {
'simple-import-sort/imports': 'error',
'simple-import-sort/exports': 'error',
},
});
{
"scripts": {
"lint": "oxlint",
"lint:fix": "oxlint --fix"
}
}
Terminal window
npm run lint # Lint all files
npm run lint:fix # Fix auto-fixable problems
  • Node.js >= 22.12.0
  • Oxlint >= 1.87.0
  • TypeScript project with a tsconfig.json (for type-aware rules)
  • oxlint (>=1.87.0)
  • oxlint-tsgolint (>=7.0.0, optional): enables type-aware rules

MIT