TypeScript
Strict, end-to-end TypeScript across React, Next.js, Node.js, and NestJS.
TypeScript is the default language for every JavaScript project I start. I use it across the stack — React/Next.js frontends, Node.js and NestJS backends, shared types between client and server — with strict mode enabled and an explicit type-driven approach to API contracts.
How I work with TypeScript
I switched to TypeScript shortly after I started full-stack work and never looked back. The first benefit was obvious — fewer runtime surprises — but the deeper benefit was being able to model business invariants in the type system so they are checked at build time.
On the frontend I use TypeScript with React, Next.js, and Redux Toolkit, treating component props and Redux state as first-class types. On the backend I use it with Express, NestJS, and increasingly with Prisma + Zod for schema-as-source-of-truth setups.
I run `strict: true`, ban implicit any, and rely on discriminated unions for state machines. The type-checker is part of CI, not an afterthought, on every project I lead.
TypeScript across business domains
Modeled document-processing job states as discriminated unions so the UI could exhaustively handle every status without runtime checks.
Used shared TypeScript types between the Next.js frontend and the NestJS backend, eliminating an entire category of contract-drift bugs.
Encoded workflow stages and permission rules in the type system so invalid transitions became compile errors.
Built strongly-typed analytics event schemas with Zod validation at API boundaries.
Real issues I resolved using TypeScript
Caught a production-breaking schema change before deploy
A backend team renamed a field in a shared API contract. Because the frontend was using plain JS objects, the bug only showed up after deploy as a blank screen for users.
Introduced a shared `@org/types` package with TypeScript interfaces generated from the OpenAPI spec, consumed by both frontend and backend. CI failed on contract drift.
Contract-drift bugs went from 'caught in QA or production' to 'caught in PR'. Cross-team coordination overhead dropped noticeably.
Replaced a runtime validator with type-driven Zod schemas
A NestJS backend was using ad-hoc `if (typeof x === 'string')` checks for request validation — inconsistent and easy to forget.
Defined every request DTO as a Zod schema, derived TypeScript types from those schemas, and added a global validation pipe that rejected invalid payloads with structured errors.
Validation became consistent across every endpoint, types and runtime checks stayed in sync by construction, and frontend error handling got simpler thanks to predictable error shapes.
Modeled a multi-step workflow with discriminated unions
A compliance workflow had ~8 states with different required fields, and the existing code used optional fields everywhere — easy to misuse, easy to crash on `undefined`.
Refactored the workflow state into a discriminated union keyed by stage, so each variant declared exactly the fields it required. The compiler enforced exhaustive handling at every switch.
Eliminated several classes of null-related bugs, made onboarding new developers faster, and made the workflow code essentially self-documenting.
Often used together
Have a TypeScript project in mind?
I am open to full-time and contract work where TypeScriptis core to the stack. Let's talk about what you are building.