passsy / prefer-union-over-enumr3
Prefer a union of literals over a TypeScript enum
PublicA TypeScript enum emits runtime code and breaks type stripping; a union of string literals gives the same safety with nothing emitted.
tests, run by the registry6 passed · slowest 1.2 ms
✓fires1.2 ms
fires on an enum the agent writes
write src/status.tsfired: line 1
export enum Status {
Draft = "draft",
Released = "released",
}
export const DEFAULT_PAGE_SIZE = 20;✓fires0.9 ms
fires on a const enum
write src/direction.tsfired: line 1
const enum Direction {
Up,
Down,
}✓quiet1.0 ms
stays quiet on an enum that was already there when the agent edits another line
write src/status.ts · wrote line 6stayed quiet
export enum Status {
Draft = "draft",
Released = "released",
}
export const DEFAULT_PAGE_SIZE = 20;✓quiet0.9 ms
stays quiet on a union of literals
write src/status.tsstayed quiet
export type Status = "draft" | "released";
export const STATUSES = ["draft", "released"] as const;✓quiet0.9 ms
stays quiet on enum in a comment, a string or another word
write src/label.tsstayed quiet
// enum Status was replaced by a union.
const enumerate = (items: string[]) => items.entries();
const label = "enum Status {";✓skips0.0 ms
stays quiet in a declaration file
write types/vendor.d.tsno handler of the detector wants this event
export declare enum VendorMode {
Fast,
Safe,
}detector.test.tseach detect() call runs the real detectorEdit
import { expect, test } from "vitest";
import { detect, edit, source, write } from "@wellactually/sdk/v3/test";
const status = source`
export enum Status {
Draft = "draft",
Released = "released",
}
export const DEFAULT_PAGE_SIZE = 20;
`;
test("fires on an enum the agent writes", () => {
expect(detect(write("src/status.ts", status))).toEqual([{ line: 1 }]);
});
test("fires on a const enum", () => {
const code = source`
const enum Direction {
Up,
Down,
}
`;
expect(detect(write("src/direction.ts", code))).toEqual([{ line: 1 }]);
});
test("stays quiet on an enum that was already there when the agent edits another line", () => {
expect(detect(edit("src/status.ts", status, { written: "export const DEFAULT_PAGE_SIZE = 20;" }))).toEqual([]);
});
test("stays quiet on a union of literals", () => {
const code = source`
export type Status = "draft" | "released";
export const STATUSES = ["draft", "released"] as const;
`;
expect(detect(write("src/status.ts", code))).toEqual([]);
});
test("stays quiet on enum in a comment, a string or another word", () => {
const code = source`
// enum Status was replaced by a union.
const enumerate = (items: string[]) => items.entries();
const label = "enum Status {";
`;
expect(detect(write("src/label.ts", code))).toEqual([]);
});
test("stays quiet in a declaration file", () => {
const code = source`
export declare enum VendorMode {
Fast,
Safe,
}
`;
expect(detect(write("types/vendor.d.ts", code))).toEqual([]);
});