一键导入
quality-code
TypeScript/full-stack review: type safety (branded, unions, end-to-end), real tests over mocks, OpenTelemetry, right abstractions.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
TypeScript/full-stack review: type safety (branded, unions, end-to-end), real tests over mocks, OpenTelemetry, right abstractions.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | quality-code |
| description | TypeScript/full-stack review: type safety (branded, unions, end-to-end), real tests over mocks, OpenTelemetry, right abstractions. |
Apply these principles when writing or reviewing TypeScript code.
Use the type system to make invalid states fail at compile time. Fewer reachable states = easier code to read and change.
Brand primitives so they can't be mixed up. Validate once at the boundary; downstream code trusts the type.
type PhoneNumber = string & { __brand: "PhoneNumber" };
function parsePhone(input: string): PhoneNumber {
if (!/^\+?\d{10,15}$/.test(input)) throw new Error(`Invalid: ${input}`);
return input as PhoneNumber;
}
function sendSMS(to: PhoneNumber, body: string) {
/* input is trusted */
}
If the project already uses a library with native branded-type support (e.g. Effect), use their primitives instead of rolling your own.
// Don't — invalid combos representable
type State = { loading: boolean; user?: User; error?: string };
// Do — only valid states exist
type State =
| { status: "loading" }
| { status: "success"; user: User }
| { status: "error"; error: string };
DB schema → server → client should share types without manual duplication. Use whatever end-to-end type tool the project already has (tRPC, oRPC, Elysia, TanStack Start). A users.email branded as Email should arrive on the client still branded.
Don't restate types you can derive. Reach for Pick, Omit, Parameters, ReturnType, Awaited, typeof etc. before writing a new interface. For function arguments, infer from the source instead of typing them by hand:
// Don't — duplicate shape, drifts when the row changes
type UserSummary = { id: string; email: Email };
function renderUser(u: UserSummary) {
/* ... */
}
// Do — derive from the source of truth
type User = Awaited<ReturnType<typeof db.query.users.findFirst>>;
function renderUser(u: Pick<User, "id" | "email">) {
/* ... */
}
// Don't — swap two args, still compiles
sendEmail("Welcome!", "Hi there");
// Do — order-independent, self-documenting
sendEmail({ to: "alice@x.com", body: "Hi there" });
Skip on hot perf-critical paths; use elsewhere by default.
For libraries or code that doesn't want to pick a validator, accept StandardSchemaV1<unknown, T>.
Don't mock things you can run. Spin up real services:
bun:sqlite), not a mock DBMock only third-party services that have no test environment.
When adding observability, instrument with OTel spans. The setup cost pays back the first time a user sends a request ID and you can answer instead of guess.
Run the announcement round for a finished project: attribution check, directory submissions, launch-post drafts in Mike's voice. Drafts only — never posts. Trigger: /announce <project>, 'announce', 'launch round', 'tell people about'.
Novel ignition ritual for story-bible: 3-line 'previously on' + one pulling question. Body-double for getting into writing state, zero obligation. Trigger: /ignite, 'ignite', 'novel time', 'story time'.
Read/post Twitter/X via `bird` CLI: tweets, threads, search, timelines, bookmarks, follows, lists, media.
Drive VISIBLE Chrome with real profile/logins (CDP :9222). Screenshots, JS eval, interactive element picking, cookies. Frontend testing, authed flows, anything user should see. Headless text-only reading → Browser* tools. Linux + macOS.
Read before git commits.
Compact current conversation into handoff doc for another agent.