plugins/typescript-dev/skills-pi/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
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. NOT for generic implementation planning that does not read or write `.spec/` files.
development
Simple web development with HTML, CSS, JS, and HTMX. Use when working with .html, .css, or .htmx files, web templates, stylesheets, or vanilla JS scripts. NOT for React/Vue/Angular (use writing-typescript) or Node.js backends.
tools
Idiomatic TypeScript development. Use when writing TypeScript code, Node.js services, React apps, or TypeScript design advice. Emphasizes strict typing, boundary validation, composition, fast feedback, behavior tests, and project-configured tooling. NOT for Go, Python, Rust, plain HTML/CSS/JS, or server-rendered templates (use writing-web).
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, CI `run:` shell bodies, or command-runner recipes. Emphasizes portability, quoting, safe filesystem/process handling, non-TUI CLI tools, ShellCheck, shfmt, Bats, and ShellSpec. NOT for Python, Rust, TypeScript, Go, web code, or GitHub Actions workflow/job/permissions semantics; use operating-infra.