Loading...
Loading...
TypeScript code quality patterns for writing and reviewing code. Covers type safety, clean code, functional patterns, Zod usage, and error handling. Triggers on: add entity, create service, add repository, create comparator, add formatter, deployment stage, GraphQL query, GraphQL mutation, bootstrap method, diff support, command handler, Zod schema, error class, implement feature, add function, refactor code, clean code, functional patterns, map filter reduce, satisfies operator, type guard, code review, PR review, check implementation, audit code, fix types.
npx skill4agent add saleor/configurator reviewing-typescript-code*Service*Repository*Comparator*Formatter*ErrorBaseErroranyas unknown as T!readonlysatisfies// BAD - Avoid these patterns
const result: any = someOperation();
const value = maybeUndefined!;
const data = response as unknown as MyType;
// GOOD - Use these patterns
type EntitySlug = string & { readonly __brand: unique symbol };
const isSlugBasedEntity = (entity: unknown): entity is { slug: string } => { ... };
const ENTITY_TYPES = ['categories', 'products'] as const;
// GOOD - satisfies for type validation while preserving literal types
interface ConfigShape {
readonly MAX_ITEMS: number;
readonly TIMEOUT: number;
}
const CONFIG = {
MAX_ITEMS: 10,
TIMEOUT: 5000,
} as const satisfies ConfigShape;
// CONFIG.MAX_ITEMS is `10`, not just `number`
// GOOD - Template literal type validation with satisfies
type CliFlag = `--${string}`;
const FLAGS = ["--json", "--verbose"] as const satisfies readonly CliFlag[];ishasshouldcan// BAD naming
const data = process(items);
const flag = check(user);
// GOOD naming
const categoriesToProcess = await fetchPendingCategories();
const isEntitySlugUnique = await validateSlugUniqueness(slug);
// BAD - Magic numbers
if (items.length > 10) { truncate(); }
const preview = text.slice(0, 30);
// GOOD - Named constants
const LIMITS = { MAX_ITEMS: 10, MAX_PREVIEW: 30 } as const;
if (items.length > LIMITS.MAX_ITEMS) { truncate(); }
const preview = text.slice(0, LIMITS.MAX_PREVIEW);
// BAD - Long if-else chain
function classify(error: Error): AppError {
if (error.message.includes("network")) return new NetworkError();
if (error.message.includes("auth")) return new AuthError();
if (error.message.includes("validation")) return new ValidationError();
return new UnexpectedError();
}
// GOOD - Registry pattern
interface ErrorMatcher {
matches: (msg: string) => boolean;
create: (error: Error) => AppError;
}
const ERROR_MATCHERS: ErrorMatcher[] = [
{ matches: (m) => m.includes("network"), create: () => new NetworkError() },
{ matches: (m) => m.includes("auth"), create: () => new AuthError() },
];
function classify(error: Error): AppError {
const matcher = ERROR_MATCHERS.find((m) => m.matches(error.message));
return matcher?.create(error) ?? new UnexpectedError();
}MapformapfilterreduceforEachmapflatMapmapfilter// BAD - Mutation
items.push(newItem);
entity.status = 'active';
// GOOD - Immutable
const updatedItems = [...items, newItem];
const updatedEntity = { ...entity, status: 'active' };
// BAD - Imperative loop with push
const lines: string[] = [];
for (const item of items) {
lines.push(formatItem(item));
}
// GOOD - Functional map
const lines = items.map(formatItem);
// BAD - forEach with conditional push
const results: Result[] = [];
items.forEach((item) => {
const match = item.match(regex);
if (match) {
results.push({ id: match[1] });
}
});
// GOOD - map + filter with type guard
const results = items
.map((item) => {
const match = item.match(regex);
return match ? { id: match[1] } : null;
})
.filter((r): r is Result => r !== null);
// BAD - Nested forEach
items.forEach((item) => {
lines.push(`Name: ${item.name}`);
item.details.forEach((d) => lines.push(` - ${d}`));
});
// GOOD - flatMap for nested structures
const lines = items.flatMap((item) => [
`Name: ${item.name}`,
...item.details.map((d) => ` - ${d}`),
]);z.infer<>safeParse// GOOD pattern
const CategorySchema = BaseEntitySchema.extend({
slug: EntitySlugSchema,
parent: EntitySlugSchema.optional(),
});
type CategoryInput = z.infer<typeof CategorySchema>;BaseErrorGraphQLError.fromCombinedError()ZodValidationError.fromZodError()// GOOD error pattern
class EntityValidationError extends BaseError {
constructor(message: string, public readonly validationIssues: ValidationIssue[] = []) {
super(message, 'ENTITY_VALIDATION_ERROR');
}
getSuggestions(): string[] {
return ['Check entity configuration against schema'];
}
}Map// BAD - Creates new object each iteration
const result = items.reduce((acc, item) => ({ ...acc, [item.id]: item }), {});
// GOOD - Mutates Map directly
const result = items.reduce((acc, item) => acc.set(item.id, item), new Map());{baseDir}/docs/CODE_QUALITY.md{baseDir}/docs/ARCHITECTURE.md{baseDir}/biome.jsonadding-entity-typesdesigning-zod-schemasvalidating-pre-commit.claude/rules/code-quality.mdsrc/**/*.ts