Exploring TypeScript Enums and Discriminated Unions in Message Handling
Tags: typescript, webdev, javascript, beginners
Published: 2023-10-31 09:11:00

In the realm of software development, effective communication between components is crucial. When working with TypeScript, a statically typed superset of JavaScript, it's possible to create robust data structures to represent different types of messages and their details. In this blog post, we'll take a deep dive into a TypeScript code snippet that showcases the use of enums and discriminated unions for message handling.

### Defining Message Types

To start, we define an `enum` called `MessageType` that represents the different types of messages:

```typescript
enum MessageType {
  BROADCAST,
  P2P
}
```

In this case, we have two message types: `BROADCAST` and `P2P`. These enums allow us to categorize messages into distinct groups.

### Message Details

We also define two custom types, `BroadcastDetails` and `P2PDetails`, to represent the details of each type of message. These types specify the properties that are relevant for each type:

```typescript
type BroadcastDetails = {
  sender: string;
  receiver: string[];
  broadcastName: string;
};

type P2PDetails = {
  sender: string;
  receiver: string;
};
```

`BroadcastDetails` includes properties like the sender's name, the list of receivers, and the name of the broadcast. On the other hand, `P2PDetails` represents a peer-to-peer message, involving the sender and a single receiver.

### Message Variants

Now, we define message variants using TypeScript's discriminated union feature. We create two message types, `BroadcastMessage` and `P2PMessage`, which include a `type` property from the `MessageType` enum to distinguish the message type and `messageDetails` to hold the specific message details:

```typescript
type BroadcastMessage = {
  type: MessageType.BROADCAST;
  messageDetails: BroadcastDetails;
};

type P2PMessage = {
  type: MessageType.P2P;
  messageDetails: P2PDetails;
};

type MessageDetails = BroadcastMessage | P2PMessage;
```

By including the `type` property, we create a discriminated union, making it easy to identify and work with different message types. The `MessageDetails` type is defined as a union type of the `BroadcastMessage` and `P2PMessage` types, which means it can be either a `BroadcastMessage` or a `P2PMessage`.

### Message Container

To encompass the message and its details, we define a `Message` type that combines the message content with the specific message details:

```typescript
type Message = { message: string } & MessageDetails;
```

This allows us to create messages with a content string and the relevant message details.

### Message Instances

We then create two message instances, `brdcst` and `p2p`, each representing a different message type:

```typescript
const brdcst: Message = {
  message: 'this is a broadcast',
  type: MessageType.BROADCAST,
  messageDetails: {
    broadcastName: 'test',
    sender: '+01 999-999-999',
    receiver: ['+01 000-000-0001', '+01 000-000-0002']
  };
};

const p2p: Message = {
  message: 'this is a P2P message',
  type: MessageType.P2P,
  messageDetails: {
    sender: '+01 999-999-999',
    receiver: '+01 000-000-0001'
  };
};
```

In `brdcst`, we create a broadcast message with a specified broadcast name, sender, and a list of receivers. In `p2p`, we define a peer-to-peer message with a sender and a single receiver.

### Conclusion

This TypeScript code snippet exemplifies how to implement message handling using enums and discriminated unions. By defining different message types and their details, we can ensure robust communication between components while leveraging TypeScript's strong type-checking capabilities. Whether you're building a chat application, an API, or any system involving message exchange, these techniques can help you manage your messages effectively.