title
Configure Linting for Effect
id
tooling-linting
skillLevel
intermediate
applicationPatternId
tooling-and-debugging
summary
Set up Biome or ESLint with Effect-specific rules for code quality.
tags
tooling
linting
biome
eslint
rule
description
Use Biome for fast linting with Effect-friendly configuration.
author
PaulJPhilp
related
tooling-hello-world
tooling-ci-cd
lessonOrder
1
Configure Biome (recommended) or ESLint with rules that work well with Effect's functional patterns.
Good linting for Effect:
Catches errors - Unused variables, missing awaits
Enforces style - Consistent code across team
Avoids antipatterns - No implicit any, proper typing
Fast feedback - Errors in editor immediately
1. Biome Configuration (Recommended)
// biome.json
{
"$schema" : " https://biomejs.dev/schemas/1.8.0/schema.json" ,
"organizeImports" : {
"enabled" : true
},
"linter" : {
"enabled" : true ,
"rules" : {
"recommended" : true ,
"complexity" : {
"noExcessiveCognitiveComplexity" : " warn" ,
"noForEach" : " off" , // Effect uses forEach patterns
"useLiteralKeys" : " off" // Effect uses computed keys
},
"correctness" : {
"noUnusedVariables" : " error" ,
"noUnusedImports" : " error" ,
"useExhaustiveDependencies" : " warn"
},
"style" : {
"noNonNullAssertion" : " warn" ,
"useConst" : " error" ,
"noParameterAssign" : " error"
},
"suspicious" : {
"noExplicitAny" : " warn" ,
"noConfusingVoidType" : " off" // Effect uses void
},
"nursery" : {
"noRestrictedImports" : {
"level" : " error" ,
"options" : {
"paths" : {
"lodash" : " Use Effect functions instead" ,
"ramda" : " Use Effect functions instead"
}
}
}
}
}
},
"formatter" : {
"enabled" : true ,
"indentStyle" : " space" ,
"indentWidth" : 2 ,
"lineWidth" : 100
},
"javascript" : {
"formatter" : {
"semicolons" : " asNeeded" ,
"quoteStyle" : " double" ,
"trailingComma" : " es5"
}
},
"files" : {
"ignore" : [
" node_modules" ,
" dist" ,
" coverage" ,
" *.gen.ts"
]
}
}
2. ESLint Configuration (Alternative)
// eslint.config.js
import eslint from "@eslint/js"
import tseslint from "typescript-eslint"
export default tseslint . config (
eslint . configs . recommended ,
...tseslint . configs . strictTypeChecked ,
{
languageOptions : {
parserOptions : {
project : true ,
tsconfigRootDir : import . meta. dirname ,
} ,
} ,
rules : {
// TypeScript strict rules
"@typescript-eslint/no-unused-vars" : [
"error" ,
{ argsIgnorePattern : "^_" }
] ,
"@typescript-eslint/no-explicit-any" : "warn" ,
"@typescript-eslint/explicit-function-return-type" : "off" ,
"@typescript-eslint/no-floating-promises" : "error" ,
// Effect-friendly rules
"@typescript-eslint/no-confusing-void-expression" : "off" ,
"@typescript-eslint/no-misused-promises" : [
"error" ,
{ checksVoidReturn : false }
] ,
// Style rules
"prefer-const" : "error" ,
"no-var" : "error" ,
"object-shorthand" : "error" ,
"prefer-template" : "error" ,
} ,
} ,
{
files : [ "**/*.test.ts" ] ,
rules : {
"@typescript-eslint/no-explicit-any" : "off" ,
} ,
} ,
{
ignores : [ "dist/" , "coverage/" , "node_modules/" ] ,
}
)
{
"scripts" : {
"lint" : " biome check ." ,
"lint:fix" : " biome check --apply ." ,
"lint:ci" : " biome ci ." ,
"format" : " biome format --write ." ,
"format:check" : " biome format ."
}
}
// .vscode/settings.json
{
"editor.defaultFormatter" : " biomejs.biome" ,
"editor.formatOnSave" : true ,
"editor.codeActionsOnSave" : {
"quickfix.biome" : " explicit" ,
"source.organizeImports.biome" : " explicit"
},
"[typescript]" : {
"editor.defaultFormatter" : " biomejs.biome"
},
"[typescriptreact]" : {
"editor.defaultFormatter" : " biomejs.biome"
}
}
// package.json
{
"scripts" : {
"prepare" : " husky"
}
}
# .husky/pre-commit
bun run lint:ci
bun run typecheck
6. Effect-Specific Rules to Consider
// Custom rules you might want
// ❌ Bad: Using Promise where Effect should be used
{
const fetchData = async ( ) => { } // Warn in Effect codebase
}
// ✅ Good: Using Effect
{
const fetchData = Effect . gen ( function * ( ) { } )
}
// ❌ Bad: Throwing errors
{
const validate = ( x : unknown ) => {
if ( ! x ) throw new Error ( "Invalid" ) // Error
}
}
// ✅ Good: Returning Effect with error
{
const validate = ( x : unknown ) =>
x ? Effect . succeed ( x ) : Effect . fail ( new ValidationError ( ) )
}
// ❌ Bad: Using null/undefined directly
{
const maybeValue : string | null = null // Warn
}
// ✅ Good: Using Option
{
const maybeValue : Option . Option < string > = Option . none ( )
}
Feature
Biome
ESLint
Speed
⚡ Very fast
🐢 Slower
Config
Simple JSON
Complex
Plugins
Limited
Many
Formatting
Built-in
Need Prettier
Use Biome for new projects - Faster, simpler
Enable strict rules - Catch more bugs
Auto-fix on save - Reduce friction
Run in CI - Enforce standards
Ignore generated files - Don't lint build output