# core/quality/eslint/no-increment-operator.eslint.rule.ts

> 65 lines of code and 12 definitions.

Tree: GovLab Quality
Language: typescript
Canonical: https://banes-lab.com/anatomy/quality#file-quality-core-quality-eslint-no-increment-operator-eslint-rule-ts
Source text: https://banes-lab.com/source/quality/core/quality/eslint/no-increment-operator.eslint.rule.ts.txt

Listed in [core/quality/eslint](https://banes-lab.com/api/source/quality/core/quality/eslint.md), after [core/quality/eslint/no-hardcoded-secrets.eslint.rule.ts](https://banes-lab.com/source/quality/core/quality/eslint/no-hardcoded-secrets.eslint.rule.ts.md) and before [core/quality/eslint/no-inline-events.eslint.rule.ts](https://banes-lab.com/source/quality/core/quality/eslint/no-inline-events.eslint.rule.ts.md).

## Definitions

- `isParent` (lexical_declaration, line 10)
- `grandForUpdate` (lexical_declaration, line 18)
- `asParent` (lexical_declaration, line 14)
- `valueUnused` (lexical_declaration, line 26)
- `ParentNode` (interface_declaration, line 4)
- `grand` (lexical_declaration, line 22)
- `parent` (lexical_declaration, line 27)
- `create` (method_definition, line 41, exported)
- `onUpdate` (lexical_declaration, line 42, exported)
- `replacement` (lexical_declaration, line 46, exported)
- `fixable` (lexical_declaration, line 47, exported)
- `handlers` (lexical_declaration, line 60, exported)

## Contained in

- [core/quality/eslint](https://banes-lab.com/anatomy/quality/folder-quality-core-quality-eslint.md)

## Linked from

- [core/quality/eslint](https://banes-lab.com/anatomy/quality/folder-quality-core-quality-eslint.md)

## Source

```typescript
import type { Rule } from "eslint";
import { govlabMeta } from "#core/factories/eslint.factory";

interface ParentNode {
    type: string;
    update?: unknown;
    parent?: ParentNode;
}

const isParent = function isParent(value: unknown): value is ParentNode {
    return value !== null && typeof value === "object" && "type" in value;
};

const asParent = function asParent(value: unknown): ParentNode | null {
    return isParent(value) ? value : null;
};

const grandForUpdate = function grandForUpdate(parent: ParentNode): boolean {
    if (parent.type !== "SequenceExpression") {
        return false;
    }
    const grand = parent.parent;
    return grand?.type === "ForStatement" && grand.update === parent;
};

const valueUnused = function valueUnused(node: Rule.Node): boolean {
    const parent = asParent(node.parent);
    if (parent === null) {
        return false;
    }
    if (parent.type === "ExpressionStatement") {
        return true;
    }
    if (parent.type === "ForStatement" && parent.update === node) {
        return true;
    }
    return grandForUpdate(parent);
};

export default {
    create(context: Rule.RuleContext): Rule.RuleListener {
        const onUpdate = (node: Rule.Node): void => {
            if (node.type !== "UpdateExpression") {
                return;
            }
            const replacement = node.operator === "++" ? "+=" : "-=";
            const fixable = valueUnused(node);
            context.report({
                data: { operator: node.operator, replacement },
                ...(fixable
                    ? {
                          fix: (fixer): Rule.Fix =>
                              fixer.replaceText(node, `${context.sourceCode.getText(node.argument)} ${replacement} 1`),
                      }
                    : {}),
                messageId: "unexpected",
                node,
            });
        };
        const handlers: [string, (node: Rule.Node) => void][] = [["UpdateExpression", onUpdate]];
        return Object.fromEntries(handlers);
    },
    meta: govlabMeta({
        canonical: ["operator-style"],
        description: "Disallow the ++ and -- operators; use `+= 1` / `-= 1` (fixed where the value is unused)",
        fixable: "code",
        messages: { unexpected: "Unary operator '{{operator}}' is not allowed; use '{{replacement}} 1'." },
        ruleId: "no_increment_operator",
        type: "suggestion",
    }),
} satisfies Rule.RuleModule;
```
