plugins/typescript-dev/skills/writing-typescript/SKILL.md
Idiomatic TypeScript development. Use when writing TypeScript code, Node.js services, React apps, or discussing TS patterns. Emphasizes strict typing, composition, and modern tooling (bun/vite).
npx skillsauth add alexei-led/claude-code-config writing-typescriptInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
strict, noUncheckedIndexedAccess, exactOptionalPropertyTypes, no any by default, and unknown for untrusted input.Result/discriminated unions or typed thrown errors at boundaries.bunx tsc --noEmit, bun test, and lint/format commands when configured.Strict Mode Always
any as a bug—use unknown for untrusted inputInterface vs Type
Discriminated Unions
kind/type tag for variantsFlat Control Flow
Result Type Pattern
// GOOD: discriminated union for state
type LoadState<T> =
| { status: "idle" }
| { status: "loading" }
| { status: "success"; data: T }
| { status: "error"; error: string };
// BAD: boolean flags
type LoadState = {
isLoading: boolean;
isError: boolean;
data: T | null;
error: string | null;
};
// GOOD: guard clauses, early returns
function process(user: User | null): Result<Data> {
if (!user) return err("no user");
if (!user.isActive) return err("inactive");
if (user.role !== "admin") return err("not admin");
return ok(doWork(user)); // happy path at end
}
// BAD: nested conditions
function process(user: User | null): Result<Data> {
if (user) {
if (user.isActive) {
if (user.role === "admin") {
return ok(doWork(user));
}
}
}
return err("invalid");
}
function isUser(value: unknown): value is User {
return (
typeof value === "object" &&
value !== null &&
"id" in value &&
"name" in value
);
}
// Predicate helper for flat code
const isActiveAdmin = (u: User | null): u is User & { role: "admin" } =>
!!u && u.isActive && u.role === "admin";
type Result<T, E = Error> = { ok: true; value: T } | { ok: false; error: E };
const ok = <T>(value: T): Result<T, never> => ({ ok: true, value });
const err = <E>(error: E): Result<never, E> => ({ ok: false, error });
async function fetchUser(
id: string,
): Promise<Result<User, "not-found" | "network">> {
try {
const res = await fetch(`/users/${id}`);
if (res.status === 404) return err("not-found");
if (!res.ok) return err("network");
return ok(await res.json());
} catch {
return err("network");
}
}
function area(shape: Shape): number {
switch (shape.kind) {
case "circle":
return Math.PI * shape.radius ** 2;
case "square":
return shape.size ** 2;
case "rect":
return shape.width * shape.height;
default: {
const _exhaustive: never = shape; // Error if variant missed
return _exhaustive;
}
}
}
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true,
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true,
"noImplicitReturns": true,
"noImplicitOverride": true,
"isolatedModules": true
}
}
bun install # Install deps
bun run build # Build
bun test # Test
bun run lint # Lint
bun run format # Format
After generating code, always verify it compiles, tests pass, and lint runs when configured:
bunx tsc --noEmit
bun test
bun run lint
bun run format --check
Use the project's configured commands if different.
tools
Idiomatic shell development for POSIX sh, Bash, Zsh, Fish, hooks, CI shell steps, and scriptable CLI glue. Use when writing or changing `.sh`, `.bash`, `.zsh`, `.fish`, `.bats`, shell functions, shell pipelines, or command-runner recipes. Emphasizes portability, quoting, safe filesystem/process handling, non-TUI CLI tools, ShellCheck, shfmt, Bats, and ShellSpec. NOT for Python, TypeScript, Go, web code, or infrastructure operations.
tools
Use when planning, executing, checkpointing, finishing, or inspecting lightweight spec-driven work. Runs one task at a time using `.spec/` markdown files and the bundled `specctl` helper. NOT for broad product discovery beyond a short requirement interview.
testing
Author, inspect, troubleshoot, and review infrastructure across IaC, Kubernetes, cloud resources, containers, CI/CD, and Linux hosts. Use when changing Terraform/OpenTofu, Kubernetes, Helm, Kustomize, Dockerfiles, GitHub Actions, AWS, GCP, Cloud Run, BigQuery, IAM, logs, instances, or service health. NOT for deploy/apply/rollback workflows (see deploying-infra). NOT for shell scripts or generic command pipelines (see writing-shell).
development
Configure safe git workflow hygiene: pre-commit/pre-push hooks, Gitleaks secret scanning, .gitignore rules, local git config, and guardrails. Use when setting up git hooks, gitleaks/git leaks, staged pre-commit checks, pre-push validation, core.hooksPath, .gitignore, or git config best practices. NOT for creating commits (use committing-code), cleaning branches/worktrees (use cleanup-git), or creating worktrees (use using-git-worktrees).