active

Anti-AI Code Slop

Safe
User-Verified

Identify and eliminate the 10 most common AI over-engineering patterns that inflate code complexity without adding value.

@api/anti-ai-code-slop

coding
quality
refactoring
ai
best-practices

Anti-AI Code Slop

Identify and eliminate the 10 most common AI over-engineering patterns that inflate code complexity without adding value.

Overview

AI coding assistants produce characteristic over-engineering patterns: defensive code for impossible scenarios, unnecessary abstractions, self-evident comments, and premature generalization. This skill trains you to recognize and eliminate AI code slop before it ships.

Inspired by community research on AI-generated code anti-patterns.

The 10 AI Code Slop Patterns

Pattern 1: Self-Evident Comments

Comments that describe exactly what the code already says.

typescript
// Bad — AI slop
const userId = user.id  // Get the user's ID
const total = price * quantity  // Calculate total by multiplying price by quantity
users.push(newUser)  // Add the new user to the users array

// Good — no comment needed, or comment explains WHY not WHAT
const userId = user.id

Rule: Only comment when the code cannot be made self-explanatory, or when you need to explain why a non-obvious choice was made.

Pattern 2: Defensive Error Handling for Impossible Scenarios

Catching errors that cannot occur given the system's invariants.

typescript
// Bad — AI slop
function getUser(users: User[], id: string): User {
  const user = users.find(u => u.id === id)
  if (!user) {
    throw new Error(`User not found: ${id}`)  // caller guarantees id is valid
  }
  return user
}

// Good — trust internal invariants
function getUser(users: User[], id: string): User {
  return users.find(u => u.id === id)!
}

Rule: Validate at system boundaries (user input, external APIs). Trust internal code and framework guarantees. Don't add error handling for scenarios that can't happen.

Pattern 3: One-Time Abstractions

A helper function or wrapper that is called exactly once and wraps a single operation that was already simple.

typescript
// Bad — AI slop
function formatUserDisplayName(user: User): string {
  return `${user.firstName} ${user.lastName}`
}
// ...called once, 3 lines away from the definition

// Good — just inline it
const displayName = `${user.firstName} ${user.lastName}`

Rule: Three similar calls justify an abstraction. One call does not. A helper wrapping a single stdlib call adds indirection without removing repetition.

Pattern 4: Backwards-Compatibility Shims for Unshipped Code

Type aliases, re-exports, or renamed variables kept for "compatibility" when the original was never in production.

typescript
// Bad — AI slop (this code was never shipped anywhere)
export type UserRecord = User  // backwards compat alias
export { getUserById as fetchUser }  // old name kept for migration
const _unusedConfig = config  // _prefix instead of deletion

// Good — delete unused code

Rule: If the code was never in production and has no external callers, there is nothing to be backward-compatible with. Delete it.

Pattern 5: Feature Flags for Internal Decisions

Using boolean flags or configuration variables for decisions that are purely internal and will never vary at runtime.

typescript
// Bad — AI slop
const USE_NEW_VALIDATION = true  // feature flag that has been true since day one

function validate(data: unknown) {
  if (USE_NEW_VALIDATION) {
    return newValidate(data)
  }
  return oldValidate(data)  // never reached
}

// Good
function validate(data: unknown) {
  return newValidate(data)
}

Rule: Feature flags are for rollout management. Internal code paths that will never be toggled in production should just be the code.

Pattern 6: Premature Options-Object Generalization

Converting a function with 2 specific parameters to an options object "for future flexibility" before any second usage exists.

typescript
// Bad — AI slop
interface CreateUserOptions {
  name: string
  email: string
  role?: string       // added "just in case"
  sendEmail?: boolean // not used yet
}

function createUser(options: CreateUserOptions) { ... }

// Good — simple parameters for simple calls
function createUser(name: string, email: string) { ... }

Rule: Generalize when you have 3+ callers with varying needs. Two parameters does not need an options object.

Pattern 7: Redundant JSDoc on Self-Evident Functions

Documentation comments that restate what the function signature already communicates.

typescript
// Bad — AI slop
/**
 * Gets the user by ID.
 * @param id - The user's ID
 * @returns The user object
 */
function getUserById(id: string): User { ... }

// Good — no docs needed; the name and types explain it
function getUserById(id: string): User { ... }

Rule: Document why something non-obvious is done, or the contract when it's not obvious from types. Don't document "this function does what its name says."

Pattern 8: Over-Typed Single-Use Structures

Defining an interface or type alias for a value that is created once and used once in the same function.

typescript
// Bad — AI slop
interface ValidationResult {
  isValid: boolean
  errors: string[]
}

function validate(input: string): ValidationResult {
  const result: ValidationResult = { isValid: true, errors: [] }
  // ...
  return result
}

// Good — inline type is fine here, or just return the object
function validate(input: string): { isValid: boolean; errors: string[] } {
  return { isValid: true, errors: [] }
}

Rule: Named types earn their place when used in 3+ places, in public APIs, or when naming the concept aids readability. Single-use internal structures don't need names.

Pattern 9: Unnecessary Async Wrapping

Wrapping synchronous operations in async/await or Promise.resolve() with no actual async work.

typescript
// Bad — AI slop
async function getConfig(): Promise<Config> {
  const config = JSON.parse(fs.readFileSync('config.json', 'utf-8'))  // sync!
  return config
}

// Or worse:
async function add(a: number, b: number): Promise<number> {
  return a + b
}

// Good
function getConfig(): Config {
  return JSON.parse(fs.readFileSync('config.json', 'utf-8'))
}

Rule: Use async only when the function actually awaits something. Don't future-proof synchronous functions with async wrappers "just in case."

Pattern 10: Significance-Inflating Variable Names

Naming variables with grandeur that inflates the importance of routine operations.

typescript
// Bad — AI slop
const comprehensiveUserDataFetchResult = await getUser(id)
const criticalAuthenticationToken = generateToken(user)
const transformedAndNormalizedInputData = input.trim()

// Good
const user = await getUser(id)
const token = generateToken(user)
const trimmed = input.trim()

Rule: Variable names describe what they hold, not how important it is. "result," "user," "token" are fine names.

Review Checklist

Run before every code review or self-review:

code
[ ] Every comment explains WHY, not WHAT
[ ] No error handling for scenarios that cannot occur
[ ] No function called exactly once that wraps a single line
[ ] No type aliases or re-exports for code that was never shipped
[ ] No feature flags that are always one value
[ ] No options objects for functions with 1-2 natural parameters
[ ] No JSDoc on self-evident function signatures
[ ] No named interfaces used in only one place
[ ] No async functions without actual await calls
[ ] Variable names describe content, not importance

Application Scope

Apply to: code you are writing or reviewing for production use.

Do not apply to:

  • Public APIs where backwards compatibility is a real concern
  • Libraries where the options object pattern is conventional
  • Code that genuinely needs future extensibility (well-established extension points)
  • Existing code bases where consistency with surrounding patterns matters more than purity
Dormant$0/mo

$20 more to next tier

Info

Created March 18, 2026
Version 1.0.0
Agent-invoked
Terminal output

Demo

Embed

Add this skill card to any webpage.

<iframe src="https://skillslap.com/skill/2d1296e1-16a9-4d97-b75a-9ca3e752720c/embed"
        width="400" height="200"
        style="border:none;border-radius:12px;"
        title="SkillSlap Skill: Anti-AI Code Slop">
</iframe>