19. Always Affirmative
Negations burn brain cycles — every "not" forces the reader to flip the logic. Prefer affirmative names and conditions to make code faster to read and safer to change.

"Don't ever not avoid negative logic."
Sounds confusing? Exactly.
Negations burn brain cycles. Every "not" forces readers (yes, developers too 😉) to mentally flip the logic. Prefer affirmative names and conditions.
🔎 Example (original)
if (!this.isNotLoggedIn() && !isNotEmpty) {
// ...
}
Do you parse that in one go? Probably not.
✅ Better (affirmative, readable)
const isLoggedIn = this.isAuthenticated();
const hasItems = items.length > 0;
if (isLoggedIn && hasItems) {
// ...
}
Guidelines
1. Name what's true when the flag is true.
- ❌
isNotLoggedIn→ ✅isLoggedIn - ❌
isNotEmpty→ ✅hasItems - ❌
noAccess→ ✅hasAccess/canAccess
2. Avoid double negatives.
❌ !isNotReady → ✅ isReady
Use well-named intermediates when needed:
const hasAccess = user.roles.includes('admin');
const isReady = hasConfig && hasAccess;
if (!isReady) return;
3. Rename functions; invert their internals if needed.
❌ function isNotLoggedIn() { return !token; }
✅ function isLoggedIn() { return Boolean(token); }
4. Pick positive words for intent.
canEdit, shouldRender, mustRedirect, hasPermission, isVisible.
5. Be pragmatic with domain language.
"invalid", "expired", "denied" are fine when they describe a state.
Avoid isNotValid → use isInvalid.
Mini refactor checklist
- Avoid patterns like
isNot*,hasNo*,without*. - Split long conditions into clearly named steps.
- Use early returns to reduce nesting.
- Add tests around the new affirmative naming.
ESLint hints (optional)
Discourage negated conditions:
// .eslintrc
{ "rules": { "no-negated-condition": "warn" } }
Flag names starting with isNot (TS):
{
"rules": {
"@typescript-eslint/naming-convention": [
"warn",
{
"selector": "variableLike",
"filter": { "regex": "^isNot[A-Z].*", "match": true },
"format": null
}
]
}
}
✨ TL;DR
Naming is developer UX. Affirmative names make code faster to read, easier to review, and safer to change.
What's the last double negative you removed from your codebase? 👇


