Channel Directions in TypeScript

When using functions that work with asynchronous operations in TypeScript, you can specify if a function is meant to only send or receive values. This specificity increases the type-safety of the program.

import { Subject } from 'rxjs';

// This `ping` function only accepts a Subject for sending
// values. It would be a compile-time error to try to
// receive on this Subject.
function ping(pings: Subject<string>, msg: string) {
    pings.next(msg);
}

// The `pong` function accepts one Subject for receives
// (`pings`) and a second for sends (`pongs`).
function pong(pings: Subject<string>, pongs: Subject<string>) {
    pings.subscribe(msg => {
        pongs.next(msg);
    });
}

function main() {
    const pings = new Subject<string>();
    const pongs = new Subject<string>();
    
    ping(pings, "passed message");
    pong(pings, pongs);
    
    pongs.subscribe(msg => {
        console.log(msg);
    });
}

main();

To run the program:

$ ts-node channel-directions.ts
passed message

In this TypeScript version, we use RxJS Subjects to mimic the behavior of channels. Subjects can both emit values and subscribe to them, making them a good analog for bidirectional channels.

The ping function takes a Subject and sends a message to it using the next method. The pong function subscribes to the pings Subject and forwards any received message to the pongs Subject.

In the main function, we create two Subjects, call ping and pong, and then subscribe to the pongs Subject to log the received message.

This approach demonstrates how TypeScript and RxJS can be used to implement patterns similar to channel directions in other languages, providing type-safe communication between different parts of an asynchronous program.