en un clic
typescript
// TypeScript anti-slop guardrails. Use when writing or reviewing .ts, .tsx, and .mts files. Covers patterns that Biome, tsc, and rslint do not catch.
// TypeScript anti-slop guardrails. Use when writing or reviewing .ts, .tsx, and .mts files. Covers patterns that Biome, tsc, and rslint do not catch.
Generate a narrative version release blog post from commits within a tag range. Use when the user wants to draft an article-style release blog (overview + a few feature highlights + a short list of minor changes), not a commit-dump release note. Asks the user to multi-select which features to highlight, then writes a bilingual draft under website/docs/{en,zh}/blog/.
Create or update draft GitHub releases for the current project's main GitHub repository, then organize GitHub-generated release notes into user-friendly sections without rewriting release note items. Use for preparing, formatting, categorizing, creating, or updating GitHub release notes or draft releases.
Testing workflow for the rstest monorepo. Use when running tests, writing test files, debugging test failures, or validating changes.
Feature and bug-fix development checklist. Use when implementing a new feature, fixing a bug, or making behavioral changes to ensure nothing is missed before PR.
| name | typescript |
| description | TypeScript anti-slop guardrails. Use when writing or reviewing .ts, .tsx, and .mts files. Covers patterns that Biome, tsc, and rslint do not catch. |
| metadata | {"internal":true} |
Skip formatting and lint rules — tooling handles those. This skill targets patterns that produce valid-looking but poor-quality code.
When in doubt, copy the local pattern in the file you are editing rather than importing a style from elsewhere.
Comments that repeat what the next line does are noise. Only comment why, never what.
// wrong
// Set the current file path
context.setFilePath(filePath);
// Initialize the reporter
const reporter = new Reporter(config);
// right — let code speak; comment only non-obvious intent
// Force sequential execution — parallel runs corrupt shared fixture state
context.setFilePath(filePath);
const reporter = new Reporter(config);
Also avoid: section-header comments inside functions (// --- Validate ---), JSDoc that adds nothing beyond the signature, temporal markers (// added for, // Phase 1).
Do not add runtime checks that the type system already guarantees. Trust the types.
// wrong — param is already typed string
function resolvePattern(pattern: string): string {
if (typeof pattern !== 'string') {
throw new Error('pattern must be a string');
}
return glob(pattern);
}
// right — trust the type system
function resolvePattern(pattern: string): string {
return glob(pattern);
}
Also avoid: redundant ?? [] / || {} on fields that are always initialized (normalize once at construction instead), null checks on values you just produced, try/catch around code that cannot throw.
asTreat as as a last resort, not a way to silence errors. If you need as, the types are probably wrong.
// wrong — casting to escape a type error
const name = (config as any).testName;
// right — narrow or fix the type
if ('testName' in config) {
const name = config.testName;
}
as any or as unknown as X unless at a proven interop seam or test-only partial mock.anynoExplicitAny is off in this repository, so self-police. Prefer unknown + narrowing, or a generic, before reaching for any. Never let any leak into exported APIs, config types, or cross-package contracts.
Do not extract a function, class, or type that is used exactly once, unless it genuinely improves readability at the call site.
// wrong — called once, five lines away
function formatTestName(name: string): string {
return name.replace(/\.test$/, '');
}
// ... later:
const display = formatTestName(file);
// right — inline it
const display = file.replace(/\.test$/, '');
Also avoid: interfaces with single implementations, factory functions that create one thing, options objects with 10 optional fields for features that don't exist yet.
Threshold: extract when used in 3+ places, or when the extraction meaningfully shortens a complex function.
If a catch block doesn't add information or recover, delete the try/catch.
// wrong — catches and rethrows with just a message rewrite
try {
await loadConfig(path);
} catch (error) {
throw new Error(
`Failed to load: ${error instanceof Error ? error.message : error}`,
);
}
// right — use cause to preserve the chain
try {
await loadConfig(path);
} catch (error) {
throw new Error(`Failed to load config at ${path}`, { cause: error });
}
// also right — just don't catch if you add nothing
await loadConfig(path);
Also avoid: bare rethrow (catch (e) { throw e; }), empty catch blocks, catch blocks that only console.log.
When two declarations describe the same thing — types, constants, defaults, validation rules — one must derive from the other. Duplicating independently causes drift: they match today, diverge silently tomorrow. Derive via extends, Pick, ReturnType, typeof, satisfies, or simply importing the canonical definition.
Before writing a helper function, search the codebase. If it exists, import it. If it exists but isn't exported, export it. Don't create a second isObject() or normalizeSlashes().
type and interface — follow nearby code.import type for type-only imports.@default.