TypeScript WebSockets 101: Getting Started Guide
Building Real-Time Applications with Type Safety Using WebSockets in TypeScript
What are WebSockets ?
WebSockets provide a full-duplex communication channel over a single TCP connection. WebSockets enable real-time communication between the client and server, making them ideal for applications such as chat apps, live notifications, collaborative tools, etc.
HTTP Polling vs WebSockets
Before WebSockets, real-time communication was often achieved using HTTP polling. This technique involves the client repeatedly sending HTTP requests to the server at regular intervals to check for updates. While effective, polling is inefficient because it generates unnecessary network traffic and latency. WebSockets solve this problem by maintaining an open connection, allowing bidirectional communication without repeated requests.
Backend: Creating a WebSocket Server in TypeScript
Step 1: Install Dependencies
npm install ws
npm install -D typescript @types/ws
Step 2: Create a WebSocket Server
import { WebSocketServer, WebSocket } from "ws";
const wss = new WebSocketServer({ port: 8080 });
wss.on("connection", (ws: WebSocket) => {
console.log("New client connected");
ws.on("message", (message: string) => {
console.log(`Received: ${message}`);
ws.send(`Server received: ${message}`);
});
ws.on("close", () => {
console.log("Client disconnected");
});
});
console.log("WebSocket server running on ws://localhost:8080");
Frontend: Creating a WebSocket Client in React / Next.js with TypeScript
//use client; //if using Nextjs
import { useEffect, useState } from "react";
const WebSocketComponent = () => {
const [messages, setMessages] = useState<string[]>([]);
const ws = new WebSocket("ws://localhost:8080");
useEffect(() => {
ws.onopen = () => {
console.log("Connected to server");
ws.send("Hello Server...");
};
ws.onmessage = (event) => {
console.log(`Received from server: ${event.data}`);
setMessages(prev => [...prev, event.data]);
};
ws.onclose = () => {
console.log("Disconnected from server");
};
return () => ws.close(); //Please do not forget this line as clean-ups are important.
}, []);
return (
<div>
<h2>WebSocket Messages</h2>
<ul>
{messages.map((msg, index) => (
<li key={index}>{msg}</li>
))}
</ul>
</div>
);
};
export default WebSocketComponent;
Structuring WebSocket Messages with TypeScript (Interfaces)
Remember for more complex applications, always define message types:
interface ChatMessage {
user: string;
message: string;
timestamp: number;
}
Then, we can use this interface in our message handlers:
ws.onmessage = (event) => {
const data: ChatMessage = JSON.parse(event.data);
console.log(`${data.user}: ${data.message} at ${new Date(data.timestamp)}`);
};
Handling Multiple Clients
When multiple clients are connected, we can broadcast messages to all clients:
wss.on("connection", (ws) => {
ws.on("message", (message) => {
wss.clients.forEach(client => {
if (client.readyState === WebSocket.OPEN) {
client.send(message);
}
});
});
});
Conclusion
WebSockets in TypeScript provide a powerful way to build real-time applications with type safety and enhanced tooling support. By structuring WebSocket messages with TypeScript interfaces, we can ensure consistency and reduce runtime errors. Whether you're building a chat app, live dashboard, or multiplayer game, WebSockets combined with TypeScript can offer a seamless and efficient communication mechanism.
And remember, with great power comes great responsibility – so don’t forget to handle disconnections gracefully.