Refactor TypeScript in a Kent Beck style: make code read like a story for humans. Use when functions are hard to follow, mix abstraction levels, or resist debugging.
Code is for people. Computers can run anything; humans must understand it.
A good function reads like a paragraph of intent. A better one reads like a checklist.
When a value is tuned often — enabled tools, prompt strategy, step budget, feature flags — keep it visible in the top-level method.
A reader should see every operational knob without opening helpers. Helpers execute decisions; the top-level method declares them.
Prefer direct declarations over wrapper functions when the inline version is just as clear and avoids hiding choices behind a click.
If the name is weak, the design is weak.
Prefer names that read well at the call site:
getQueryParam(req) not param(req)isGibberish(text) not gibberishCheck(text)hasValidEmail(input) not emailValidation(input)buildPayload(data) not payloadBuilder(data)ensureQuotaAvailable(user) not quotaCheck(user)normalizePhoneNumber(raw) not phoneFormatter(raw)Rules of thumb:
get, parse, build, fetch, save, normalizeis, has, can, shouldensure, require, validateIf a call sounds awkward when spoken aloud, rename it.
export async function handle(req: Request) {
const param = req.nextUrl.searchParams.get('q') ?? '';
const gibberish = gibberishCheck(param);
if (gibberish) return NextResponse.json({ ok: false });
// mixed logic continues...
}
export async function handle(req: Request) {
const query = getQueryParam(req);
if (isGibberish(query)) return invalidQueryResponse();
// composed flow continues...
}
Avoid:
export default async function handler(req, res) {
// ...
const tools = selectTools(); // what did we select?
const result = await enrichContact(config, tools, firstname, lastname, email);
// prompt strategy and step budget are buried inside enrichContact
}
Prefer:
export default async function handler(req, res) {
// ...
const tools = {
think: thinkTool(),
tavilySearch: tavilySearch(),
};
const systemPrompt = buildSystemPrompt(tools);
const maxSteps = 8;
const result = await enrichContact(
config,
tools,
systemPrompt,
maxSteps,
firstname,
lastname,
email
);
}
Every operational knob is visible. Comment out a tool, change a step budget, swap a prompt — all without opening helpers.
Better testability often follows from this style, but it is a side effect. Primary objective: code that is easy for humans to read, reason about, and debug.