Fullstack CourseLearn by building
Back to week 4

Topic

Lint, format, Nest pitfalls

Definition

A linter statically analyzes source code for likely bugs and style violations, while a formatter deterministically rewrites code layout. Together they remove a category of review comments and catch mistakes before runtime.

In simpler words

A linter catches things that look like bugs before code runs. A formatter stops arguments about spacing so review can focus on logic.

Beyond generic JavaScript and TypeScript lint rules, Nest has framework-specific pitfalls that lint rules alone will not catch.

After this you can

  • Explain why format and lint are separate concerns
  • Name a Nest-specific pitfall lint alone will not catch
  • Read an ESLint or TypeScript error and know which rule it violates
  • Decide when to fix a lint warning versus suppress it with justification

Lint versus format: different jobs

Definition

A formatter such as Prettier enforces consistent whitespace, line length, and punctuation without understanding code semantics, whereas a linter such as ESLint analyzes semantics to flag unused variables, unsafe patterns, and rule violations.

In simpler words

Formatting concerns how code looks. Linting concerns whether code is likely correct.

Running them separately, formatting on save and linting in continuous integration, means style debates never reach code review; only real logic issues do.

A lint rule can be a hard error that blocks continuous integration or a warning that stays visible but non-blocking. Choose based on how confident the team is that violations are always bugs.

Autofixable lint rules, such as import ordering, should be autofixed in continuous integration or a pre-commit hook, not manually retyped by every contributor.

Nest-specific pitfalls generic lint misses

Definition

Certain Nest mistakes are structurally valid TypeScript that a generic linter will not flag, because they violate framework conventions rather than language rules.

In simpler words

Some Nest bugs compile fine and pass ESLint but still break the app, because they violate the framework own rules, not the language rules.

Forgetting to export a provider from its module compiles fine, and only fails at runtime with a dependency-resolution error when another module tries to inject it.

A missing injectable decorator on a class used as a provider, or a missing forward reference in a genuine circular dependency, are Nest wiring mistakes no ESLint rule enforces.

Placing business logic or database calls directly in a controller method instead of delegating to a service is legal TypeScript that violates the thin-controller convention Nest apps rely on for testability.

Compiles fine, breaks at runtime

// UsersModule forgets to export UsersService
@Module({ providers: [UsersService], controllers: [UsersController] })
export class UsersModule {}

// AuthModule imports UsersModule but injection still fails —
// Nest throws a dependency-resolution error at boot, not at compile time.

TypeScript has no concept of Nest module exports; only booting the application actually catches this.

When to fix versus suppress

Definition

Suppressing a lint rule with an inline disable comment should be reserved for cases where the rule is a known false positive for that specific line, documented with a reason, rather than used to silence an inconvenient but valid warning.

In simpler words

Only turn off a lint warning when the reason it is wrong here can be explained in a comment. Otherwise fix the code.

A pattern of disable comments without justification signals the team disagrees with a rule, which should change the rule rather than scatter suppressions.

Prefer fixing the root cause, such as extracting a helper, adding a missing await, or narrowing a type, over disabling the rule for convenience under deadline pressure.

Keep in mind

  • Let the formatter own whitespace debates entirely; do not hand-format in review.
  • Nest wiring mistakes are runtime errors, not compile errors, so boot the app to catch them.
  • Justify every lint suppression in a comment, or fix the underlying code instead.

Test

Check your understanding

At least 10 questions — mix of concept, syntax, practical, and logic. Score ≥80% (enforced by the API) to save progress.

Checking your session…

15 questions · concept 5 · syntax 3 · practical 4 · logic 3

1. What Nest habits prevent intermediate bugs?
Concept
2. Why keep controllers thin?
Syntax
3. Why not disable ESLint on API code?
Practical
4. Where do role checks belong?
Logic
5. Why avoid synchronize in shared environments?
Concept
6. What does Prettier buy?
Practical
7. Why validate DTOs instead of trusting TS?
Syntax
8. What is a Nest pitfall to avoid?
Logic
9. Should PR review ignore lint?
Concept
10. Which practice is worst?
Practical
11. What are the two biggest problems in this controller?
Conceptadvanced
@Get()
async list(@Query('q') q) {
  const rows = await this.dataSource.query("SELECT * FROM tickets WHERE title LIKE '%" + q + "%'");
  return rows;
}
12. Why is this controller shape good?
Syntaxintermediate
@Get()
list() {
  return this.svc.list();
}
13. Why is a class DTO with validators better than a TS interface here?
Practicalintermediate
create(@Body() dto: CreateTicketDto) {}
14. Why should a reviewer flag this in a shared-env PR?
Logicadvanced
TypeOrmModule.forRoot({ url, synchronize: true });
15. What is the cleaner Nest approach to this role check?
Conceptintermediate
@Get('admin')
admin(@Req() req) {
  if (req.user.role !== 'admin') throw new ForbiddenException();
}

Checking your session…