Terug naar de blog
14 april 2026Sergei Solod5 min leestijd

Waarom TypeScript zo goed werkt met Codex voor productiesoftware

Voor productiewerk geeft TypeScript Codex iets wat een goede prompt niet kan vervangen: machinecontroleerbare contracten, snelle compilerfeedback en een veiliger pad door grote refactors.

TypeScriptCodexAI-codingSoftwareleveringJavaScriptDeveloperworkflow

Ik formuleerde dit vroeger bewust provocerend: TypeScript is de beste taal voor Codex. Nu zou ik het nauwkeuriger zeggen. Voor het soort productiegerichte frontend- en full-stackwerk dat ik doe, is TypeScript de omgeving waarin Codex het makkelijkst te sturen, te verifiëren en te vertrouwen is.

Het belangrijkste woord is niet “TypeScript”, maar controle. AI-codingagents zijn erg goed in het produceren van plausibele code. Productiesoftware vraagt meer: code moet bestaande contracten respecteren, gedrag behouden, refactors overleven en snel falen als een aanname fout is. TypeScript maakt veel meer van die beperkingen machineleesbaar dan plain JavaScript.

Wat Codex werkelijk nodig heeft van een codebase

Een goede prompt helpt, maar is slechts één bron van context. De codebase zelf kan een taak begrijpelijk maken of het model dwingen te gokken. In de praktijk is een omgeving sterk wanneer belangrijke aannames zichtbaar en automatisch controleerbaar zijn.

  • Functiesignatures bepalen geldige input en output.
  • Interfaces en types maken domeinobjecten expliciet.
  • Unions en enums beperken geldige toestanden.
  • De compiler zet veel foute aannames direct na een edit om in concrete errors.

Een AI-agent hoeft niet de volledige applicatie perfect te begrijpen als de applicatie terugpraat zodra een contract wordt geschonden. Hoe korter die feedbacklus, hoe minder ruimte er is voor zelfverzekerd gokwerk.

Types zijn uitvoerbare context, niet alleen documentatie

Goede TypeScript-types documenteren intentie voor mensen. In een geautomatiseerde workflow hebben ze extra waarde: die documentatie is controleerbaar. Bijvoorbeeld:

type PaymentResult =
  | { ok: true; receiptId: string }
  | { ok: false; code: "declined" | "timeout" };

function getReceiptId(result: PaymentResult) {
  if (result.ok) return result.receiptId;

  return result.receiptId;
  // TypeScript: Property 'receiptId' does not exist
  // on the failure branch.
}

In JavaScript kan dezelfde fout logisch lijken totdat die branch runtime wordt uitgevoerd. TypeScript kan de aanname vóór de merge afwijzen. Voor Codex is de compilererror dus niet alleen een rode lijn in de editor, maar een precies signaal over wat het model verkeerd begreep.

Daarom geef ik de voorkeur aan expliciete domeintypes boven brede constructies zoals Record<string, any>. Hoe beter types de werkelijkheid beschrijven, hoe bruikbaarder de codebase wordt als context voor mens en AI.

De compiler maakt van fouten een feedbacklus

Ik vertrouw niet op “vraag Codex om code en accepteer het eerste antwoord”. Het proces is iteratief:

task → inspect → edit → typecheck → lint → test → review diff

Dat is saai, en juist daarom werkt het. Na elke betekenisvolle wijziging antwoordt de omgeving. Type errors vinden gebroken contracten. Lint vangt een andere klasse problemen. Tests controleren gedrag dat types niet kunnen uitdrukken. De uiteindelijke diff krijgt nog steeds menselijke review.

Een slimme prompt kan de eerste poging verbeteren. Een sterke verificatielus verbetert elke poging. Voor productie is dat veel belangrijker.

Bij grote refactors wordt TypeScript extra waardevol

Kleine lokale edits zijn eenvoudig voor bijna elke coding assistant. Het lastige geval is een wijziging die door tientallen bestanden loopt: een domeinveld hernoemen, een API-response wijzigen, componentprops aanscherpen, een union splitsen of een oude abstractie vervangen.

Met TypeScript creëert een breaking change een kaart van geraakte aannames. De compiler laat zien waar het oude contract nog wordt gebruikt. Codex kan die lijst afwerken en na iedere ronde opnieuw controleren. Dat maakt de refactor niet automatisch correct, maar wel de blast radius zichtbaar.

In een los getypeerde codebase verschijnt een gemiste dependency soms pas als bug op een scherm dat tijdens development niemand heeft geopend.

Waar TypeScript je niet redt

TypeScript is een guardrail, geen bewijs van correctheid. Belangrijke fouten blijven mogelijk:

  • Verkeerde businesslogica: perfect getypeerde code kan nog steeds het verkeerde berekenen.
  • Runtime-input: API, database, formulier of third-party service kan andere data leveren dan je compile-time aannames.
  • Ontbrekende productcontext: de compiler weet niet waarom een flow bestaat of welke edge case voor gebruikers belangrijk is.
  • Security- en architectuurfouten: geldige types garanderen geen juiste autorisatie, caching, databasegrenzen of infrastructuur.

Runtime-validatie, tests, logging, observability en review blijven dus nodig. Een schone typecheck betekent niet automatisch dat een feature correct is.

De workflow die ik gebruik voor AI-assisted changes

  1. Geef de taak een smal doel. Wat moet veranderen, wat niet, en wat zijn de acceptance criteria?
  2. Laat Codex inspecteren vóór het editen. Bestaande types, call sites, tests en naburige modules zijn vaak nuttiger dan een lange prompt.
  3. Kies de kleinste samenhangende wijziging. Een gefocuste diff is makkelijker te verifiëren dan een “behulpzame” rewrite van ongerelateerde code.
  4. Draai typecheck en lint direct. Structurele fouten moeten zichtbaar worden zolang de wijziging klein is.
  5. Draai relevante tests en voeg tests toe als gedrag verandert. Types valideren contracten; tests valideren gedrag.
  6. Review de einddiff handmatig. Naming, architectuur, duplicatie, edge cases en of het oorspronkelijke probleem echt is opgelost.

Wanneer JavaScript nog steeds genoeg is

Dit is geen argument dat JavaScript slecht is. Voor een klein script, wegwerpprototype, eenvoudige automatisering of code met weinig gedeelde state kan TypeScript weinig extra opleveren. Een JavaScript-project met uitstekende tests en duidelijke conventies kan ook een prima AI-omgeving zijn.

Mijn stelling is specifieker: hoe groter, langer levend en meer collaboratief een codebase wordt, hoe waardevoller machinecontroleerbare beperkingen zijn. En juist dan worden AI-fouten ook duurder.

De echte reden waarom ik TypeScript met Codex prefereer

TypeScript maakt Codex niet slimmer. Het maakt de omgeving minder tolerant voor slechte aannames.

In productie wil ik niet alleen een creatieve agent; ik wil een agent binnen een systeem dat continu terugmeldt wanneer hij fout zit. Types, compilererrors, lint, tests en menselijke review vormen samen dat systeem.

Als ik dus zeg dat TypeScript uitzonderlijk goed werkt met Codex, gaat het niet om taalfanatisme. Het gaat om snelle, machinecontroleerbare feedback: minder ambiguïteit, kleinere blast radius, veiligere refactors en – als verificatie serieus wordt genomen – veel betrouwbaardere engineering speed.