The Biome config file is setup only to focus on TypeScript files and ignored ".js" file. If you want to include JS files, then continue reading on what to do. (Hint: remove ".js" file filtering).
Write up assisted with AI, double check information being provided.
Installing recommended Node.js dependencies
pnpm i -D -E @biomejs/biome @types/node
pnpm i typescriptBasic command like usage:
Format, lint, and organize imports of all files
pnpm exec biome check --writeFormat and Lint and apply safe fixes
pnpm exec biome format --write
pnpm exec biome lint --write "scripts": {
"build": "tsc",
"check": "tsc --noEmit",
"watch": "tsc -w",
"format:lint": "pnpm exec biome check --write",
"format": "biome format --write",
"lint":"biome lint --write",
"tsc": "tsc"
},Detailed explanation follows. NOTE: remove comment from ".json" file.
File: biome.json
{
"$schema": "https://biomejs.dev/schemas/latest/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
},
"files": {
"ignore": [
"node_modules/**",
"dist/**",
"build/**",
".next/**",
"out/**",
"coverage/**",
"public/**",
"*.d.ts".
"*.js",
"*.min.js",
"*.min.css",
"!.github",
"!.vscode"
]
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 120,
"lineEnding": "lf",
"attributePosition": "auto"
},
"javascript": {
"formatter": {
"quoteStyle": "double",
"jsxQuoteStyle": "double",
"trailingComma": "es5",
"semicolons": "always",
"arrowParentheses": "always",
"bracketSpacing": true,
"bracketSameLine": false,
"quoteProperties": "asNeeded"
},
"linter": {
"enabled": true
},
"organizeImports": {
"enabled": true
}
},
"linter": {
"enabled": true,
"rules": {
"recommended": true,
// 🔒 Enable stricter type-related rules
"correctness": {
"noUndeclaredVariables": "error",
"noUnusedVariables": "error"
},
"style": {
// Enforce type annotations where inference might be unsafe
"noInferrableTypes": "off", // Keep explicit types even if redundant (optional)
"useExplicitType": "error" // 👈 KEY: Requires explicit type annotations in declarations
},
"suspicious": {
"noExplicitAny": "error", // 🔥 Ban `any` entirely (stronger than noImplicitAny!)
"noMisusedPromises": "error"
}
}
},
"overrides": [
{
"include": ["*.js"],
"linter": {
"enabled": false
}
}
]
}Let's break down your Biome configuration file section by section, explaining what each property does, why it matters, and what the possible values mean—based on the official Biome JSON schema you provided.
Your config is a JSON object that controls:
- How Biome formats code
- Which files to ignore
- How it lints (static analysis)
- How it interacts with Git
- How it overrides behavior for specific file types
Now, let’s go line by line.
"$schema": "https://biomejs.dev/schemas/latest/schema.json"- Tells editors (like VS Code) and tools where to find the JSON Schema for validation and autocomplete.
- Using
/latest/ensures you always get the schema for the most recent stable Biome version.
- Defined in root as:
"type": ["string", "null"] - Optional but highly recommended for tooling support.
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
}| Property | Value | Meaning |
|---|---|---|
enabled |
true |
Enables VCS integration (Git-aware features) |
clientKind |
"git" |
Only supported VCS. Tells Biome to use Git. |
useIgnoreFile |
true |
Biome respects .gitignore — ignores files Git ignores |
- Prevents linting/formatting of
node_modules/, build artifacts, etc., even if not listed infiles.ignore. - Makes config DRY — you don’t duplicate ignore patterns.
✅ Best practice: keep
useIgnoreFile: trueunless you have a special reason not to.
"files": {
"ignore": [
"node_modules/**",
"dist/**",
"build/**",
".next/**",
"out/**",
"coverage/**",
"public/**",
"*.d.ts",
"*.js",
"*.min.js",
"*.min.css",
"!.github",
"!.vscode"
]
}- Explicitly tells Biome which files/directories to skip entirely (for formatting, linting, and import sorting).
- Uses Unix shell-style glob patterns
/**= match recursively (e.g.,dist/**matchesdist/a/b/c.js)*.min.js= matches any minified JS file!= negation (un-ignore). So:!.github→ do process.github/(e.g., workflows)!.vscode→ do process.vscode/settings.json
⚠️ Important: These are absolute ignores — Biome won’t touch these files at all.
files.ignoreis Biome-specific.gitignoreis used only if"useIgnoreFile": true- Use
files.ignorefor things you always want ignored, even outside Git
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 80,
"lineEnding": "lf",
"attributePosition": "auto"
}These settings apply to all supported languages unless overridden.
| Property | Value | Effect |
|---|---|---|
enabled |
true |
Turns on formatting |
indentStyle |
"space" |
Uses spaces (not tabs) |
indentWidth |
2 |
2 spaces per indent |
lineWidth |
80 |
Wraps lines at 80 characters |
lineEnding |
"lf" |
Unix-style line endings (\n) |
attributePosition |
"auto" |
In JSX/HTML, puts attributes on same line if they fit, otherwise multi-line |
📝 These are generic. Language-specific overrides (like in
javascript.formatter) take precedence.
This section configures behavior only for .js, .ts, .jsx, .tsx files.
"formatter": {
"quoteStyle": "double",
"jsxQuoteStyle": "double",
"trailingComma": "es5",
"semicolons": "always",
"arrowParentheses": "always",
"bracketSpacing": true,
"bracketSameLine": false,
"quoteProperties": "asNeeded"
}| Property | Value | Meaning |
|---|---|---|
quoteStyle |
"double" |
"hello" not 'hello' |
jsxQuoteStyle |
"double" |
Same for JSX attributes: <div id="main"> |
trailingComma |
"es5" |
Trailing commas in arrays/objects, but not in function params (ES5-safe) |
semicolons |
"always" |
Always adds ; (e.g., const x = 1;) |
arrowParentheses |
"always" |
(x) => x instead of x => x |
bracketSpacing |
true |
{ foo: 1 } (space inside braces) |
bracketSameLine |
false |
JSX closing > on new line: |
<div
id="x"
>
content
</div>| quoteProperties | "asNeeded" | Only quotes object keys if required: { valid: 1, "invalid-key": 2 } |
✅ These match common TypeScript style guides (e.g., Airbnb, Standard variants).
"linter": {
"enabled": true
}- Enables JavaScript/TypeScript-aware linting (type inference, React hooks, etc.)
- Works with top-level
"linter"rules
"organizeImports": {
"enabled": true
}- Automatically sorts and removes unused imports
- Equivalent to “Organize Imports” in VS Code
"linter": {
"enabled": true,
"rules": {
"recommended": true
}
}| Property | Value | Meaning |
|---|---|---|
enabled |
true |
Turns on linting |
rules.recommended |
true |
Enables Biome’s recommended rule set, including: |
- correctness (e.g., no unreachable code) |
||
- suspicious (e.g., no ==, no console.log) |
||
- style (e.g., prefer const) |
||
- a11y, security, complexity, etc. |
🛠️ These rules auto-fix when safe (e.g., unused imports, formatting issues).
"overrides": [
{
"include": ["*.js"],
"linter": {
"enabled": false
}
}
]- Apply different settings to specific file patterns.
- For all
.jsfiles:- Disable linting (
"linter": { "enabled": false }) - But keep formatting and import sorting (since those aren’t overridden)
- Disable linting (
✅ Common use case: You’re migrating a JS codebase to TS, and don’t want lint errors in legacy
.jsfiles.
include: list of glob patterns- Any setting you specify here overrides the global or language config only for matching files
- You can override
formatter,linter,organizeImports, etc.
❗ Note: If you wanted to fully ignore
.jsfiles, you’d put*.jsinfiles.ignoreinstead.
Great! You'd like to enable noImplicitAny — a strict TypeScript rule that prevents the compiler (and linter) from inferring the any type when types aren't explicitly provided.
However, there's an important detail to understand first:
- Biome does not use the TypeScript compiler (
tsc). - Instead, Biome has its own type inference engine and linter rules.
- Therefore, Biome doesn’t have a rule literally named
noImplicitAny, but it does have equivalent or stricter rules that catch similar issues.
In Biome, the closest and most relevant rule is:
✅
noImplicitAnyLet(part of thecorrectnessgroup)
🔹 Actually, more broadly:noImplicitAny-like behavior is covered by:
noUndeclaredVariablesnoUnsafeDeclarationMerging- And especially:
noConfusingVoidType,noRedundantUndefined, etc.But the key rule that aligns with
noImplicitAnyis:The real counterpart is enforced via type-aware lint rules that detect missing type annotations in contexts where
anywould be inferred.
However, as of Biome v1.9+, there isn’t a direct 1:1 noImplicitAny rule like in tsconfig.json.
To approximate noImplicitAny behavior, you should:
- Enable stricter type-related linter rules
- Explicitly turn on rules that require type annotations in risky places
Here’s how to update your config:
| Rule | Purpose | Why It Helps Replace noImplicitAny |
|---|---|---|
useExplicitType |
Requires explicit type annotations on variable/function declarations (e.g., let x: number = 5) |
Prevents silent any by making you write types — this is Biome’s closest equivalent |
noExplicitAny |
❌ Disallows writing any explicitly |
Stronger than noImplicitAny — if you ban any, you’re forced to use proper types |
noUndeclaredVariables |
Catches variables used without being declared | Catches JS-style bugs that TS would flag |
noUnusedVariables |
Removes dead code | Helps keep types clean |
💡 Important:
useExplicitTypeis not enabled by default, even inrecommended. You must opt in.
Example:
function greet(name) { // ❌ Biome won’t infer type → potential `any`
return "Hello " + name;
}With useExplicitType: "error", Biome will require:
function greet(name: string) {
return "Hello " + name;
}This eliminates implicit any at the source.
If you absolutely need noImplicitAny as defined by TypeScript, you should:
- Keep using
tsconfig.jsonwith:{ "compilerOptions": { "noImplicitAny": true } } - And run
tsc --noEmitin CI to catch type errors - Use Biome for formatting + fast linting, and
tscfor deep type checking
Many teams use both!
✅ For most projects, enabling:
"useExplicitType": "error",
"noExplicitAny": "error"…gives you better safety than noImplicitAny alone, because it:
- Forces explicit types
- Bans
anycompletely
Let me know if you want to:
- Only apply this to
.tsfiles (not.tsx) - Allow
anyin test files - Auto-fix missing types (note: Biome cannot auto-infer and insert types — that’s beyond its scope)
| Feature | For .ts/.tsx |
For .js |
|---|---|---|
| Formatting | ✅ Yes (with your rules) | ✅ Yes (same rules) |
| Linting | ✅ Yes (recommended rules) | ❌ Disabled |
| Import Sorting | ✅ Yes | ✅ Yes |
Respects .gitignore |
✅ Yes | ✅ Yes |
Ignores dist/, node_modules/, etc. |
✅ Yes | ✅ Yes |
-
Consider linting
.jsfiles later — maybe relax rules instead of disabling:"overrides": [{ "include": ["*.js"], "linter": { "rules": { "suspicious": { "noConsole": "warn" }, "correctness": { "noUnusedVariables": "off" } } } }]
-
Add explicit
typescriptsupport?
→ Not needed! Biome treats.ts/.tsxas part ofjavascriptconfig.
— running npx tsc --noEmit will catch TypeScript type-checking errors, but only those enforced by the TypeScript compiler (tsc) based on your tsconfig.json.
- Performs full type checking using your project’s
tsconfig.json - Does NOT emit (output) any JavaScript files (thanks to
--noEmit) - Exits with a non-zero code if there are type errors → useful in CI
- Validates:
- Type mismatches
- Missing properties
- Incorrect function signatures
noImplicitAnyviolationsstrictNullChecks,strictFunctionTypes, etc.- Import/export resolution
- Decorator and JSX configuration issues
✅ This is the standard way to type-check a TypeScript project without building it.
| Feature | tsc --noEmit |
Biome |
|---|---|---|
| Type checking | ✅ Full, deep, semantic (uses TS compiler) | ❌ No full type checking (as of Biome v1.9) |
| Linting | Limited (mostly syntax/structure) | ✅ Rich linting (noExplicitAny, useExplicitType, etc.) |
| Formatting | ❌ No | ✅ Yes |
| Speed | Slower (full type inference) | Very fast |
Catches noImplicitAny |
✅ Yes, if enabled in tsconfig.json |
❌ Not directly — must use useExplicitType + noExplicitAny as workaround |
🔑 Key point: Biome does not replace
tsc --noEmitfor type safety. They are complementary.
-
Use Biome for:
- Formatting
- Fast linting (stylistic & common bugs)
- Import sorting
- Quick auto-fixes
-
Use
tsc --noEmit(ortsc --noEmit --project tsconfig.json) for:- Guaranteed type correctness
- Enforcing
noImplicitAny,strict, etc.
💡 Many teams run both in CI:
npx @biomejs/biome check . # lint + format check npx tsc --noEmit # full type check
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"strict": true,
"noImplicitAny": true,
"esModuleInterop": true,
"skipLibCheck": true,
"noEmit": true
}
}Then just run:
npx tsc(since noEmit is in config)
✅ Yes,
npx tsc --noEmitwill catch TypeScript type errors — and it’s essential for full type safety.
🛠️ Biome enhances your workflow but does not replace the TypeScript compiler for type checking.
Let me know if you want a script that runs both Biome and tsc together!