Quiz - Docs that live in the code
You’re deciding which of these declarations earns a TSDoc block. Which one earns it?
type UserInput = z.infer<typeof userInputSchema>.The cut is the public surface — a declaration read one call site away from where it lives.
The Server Action crosses a module boundary and carries a contract (preconditions, side effects, failure modes) the signature can’t show, so it earns a block.
The private helper has no second reader, and the z.infer alias is just a derived view of the schema — the schema is the doc, a block would be a copy of a copy.
A teammate writes this @param on a function with the signature createCustomer(email: string):
/** * Creates a Stripe customer. * * @param {string} email - the user's email */What’s wrong with it?
{string} type duplicates what the TypeScript signature already states — TSDoc tags never carry types.@param should always be omitted; the parameter name is enough.@param {string} is JSDoc muscle memory. JavaScript needed types in the comment because it had none; TypeScript moved the type to the signature, where the compiler keeps it correct.
The tag’s job shrinks to what the signature can’t express — the parameter’s purpose. Repeating the type just gives you a second copy that drifts.
Same line of code, two files. Which comment earns its place?
// add one to the retry countretries += 1;// Stripe retries this webhook up to 3×; cap our own retry so the two don't compound into 9 attempts.retries += 1;The test isn’t whether the line “looks complicated” — it’s whether the answer to “why is it written this way?” lives outside the file. The first comment restates the code; nothing comes from outside, so it carries zero information. The second names Stripe’s retry behavior — invisible from the line — so without it a future reader “simplifies” the cap away.
Which of these // why comments should be promoted out of prose into something the compiler or runtime enforces? Select all that apply.
// callers must run safeParse on the body before this touches the DB// don't reorder: the audit insert has to land before we enqueue the email// timestamps come back rounded to the microsecond, so compare rounded values// the same webhook can land twice and in either orderThe cut is whether the constraint is a fact about our code or about an external system.
The first two are ours: the validate-first reminder becomes a parse at the boundary, the ordering becomes one transactional function — in both the comment dissolves into a guarantee.
The last two describe Postgres’s precision and a provider’s delivery behavior; no type can hold an external system to a promise, so they stay well-written comments.
A PR splits the test suite and renames pnpm test to pnpm test:unit. The README still says pnpm test. Your teammate suggests fixing the README in a quick follow-up PR right after this one merges. Why isn’t that good enough?
main is self-contradictory — a live wrong doc in production for the whole window, and a wrong doc is worse than no doc.Code review is the one checkpoint where someone looks at the change with attention; the next checkpoint is production. A separate doc PR doesn’t escape the problem, it just narrows the drift window to zero width only if code and doc land in the same merge. A wrong doc costs the next reader the time to read it, believe it, discover it’s lying, and stop trusting every doc near it.
A reviewer wants to know which doc-drift checks they can hand off to automation and which they have to run themselves. Which of these is the one a machine can fully catch — no human judgment needed?
.env.example declares the same set of keys as env.ts.Lint catches the drift a machine can compare; the reviewer catches the drift only a human can read. Key-parity is a pure set comparison — zero judgment, the cleanest thing to automate. Whether a summary sentence still tells the truth, or whether a change was architecturally significant, requires reading intent against behavior, which no linter can do.
Quiz complete
Score by topic