Microservices with TypeScript
In this page:
Core Concept
In a TypeScript microservices architecture, each service can have its own independent tsconfig.json and dependencies, but shared request/response contracts between services still benefit from a common typed schema so they don't drift apart silently.
Example: Core Concept
interface OrderCreatedEvent {
orderId: string;
total: number;
}
// Each service has its own tsconfig, but shares this event's shape.
const event: OrderCreatedEvent = { orderId: "1", total: 50 };
console.log(event);
Basic Setup
A basic setup often uses a shared-types package (or generated types from a schema like Protobuf/OpenAPI) published to a private registry, imported by every service that needs to call or be called by another.
Example: Basic Setup
// shared-types package published to a private registry,
// imported by every service that produces/consumes these events.
interface OrderCreatedEvent { orderId: string; }
console.log("A shared-types package prevents contract drift between services");
Typed Example
A typed example: a shared interface OrderCreatedEvent { orderId: string; userId: string; total: number } is used both by the service that publishes the event and every service that subscribes to and processes it.
Example: Typed Example
interface OrderCreatedEvent {
orderId: string;
userId: string;
total: number;
}
function publishOrderCreated(event: OrderCreatedEvent) {
console.log("Publishing:", event);
}
publishOrderCreated({ orderId: "1", userId: "u1", total: 99 });
Project Usage
In a real project, versioning these shared inter-service types carefully matters more than in a monolith, since two services might deploy on different schedules and temporarily run against slightly different versions of a shared contract.
Example: Project Usage
interface OrderCreatedEventV2 {
orderId: string;
total: number;
currency: string; // added in v2
}
console.log("Services on different deploy schedules may see different versions");
Best Practices
Validate incoming inter-service messages at runtime (not just compile time) at each service boundary, since TypeScript's types vanish at runtime and can't protect a service from a malformed message sent by another service running an older version.
Example: Best Practices
interface OrderCreatedEvent { orderId: string; total: number; }
function isOrderCreatedEvent(value: any): value is OrderCreatedEvent {
return typeof value?.orderId === "string" && typeof value?.total === "number";
}
console.log(isOrderCreatedEvent({ orderId: "1", total: 10 }));
Chapter Quiz — Complete all 14 topics to unlock
0/14 topics done
Complete these topics first:
- Todo App with TypeScript
- REST API with Express + TypeScript
- React Dashboard with TypeScript
- CLI Tool with TypeScript
- Library with TypeScript
- Full Stack TypeScript App
- TypeScript Design System
- TypeScript Monorepo Project
- Authentication System
- Real-time App with Socket.io
- GraphQL API with TypeScript
- Microservices with TypeScript
- TypeScript Best Practices Review
- What to Learn Next