Developer Tools

TypeScript CLI Game: Union Types, Conditionals & Jest

Ever wonder how to properly structure TypeScript for simple CLI games? This dive into Rock-Paper-Scissors reveals practical uses for union types and the sometimes-tricky nuances of Jest testing.

Screenshot of a Rock-Paper-Scissors CLI game output showing player choice, computer choice, and result.

Key Takeaways

  • TypeScript union types offer a cleaner alternative to enums for string-based data, improving log readability.
  • Using `else if` for mutually exclusive conditions enhances code clarity and intent compared to separate `if` statements.
  • AI can be a valuable learning companion for hints and clarification, but the developer must write and understand the code themselves.

Three percent of JavaScript developers still use libraries with known security vulnerabilities. That’s a stat that should make anyone building anything publicly accessible sweat a little. It’s a constant battle out there, and understanding the fundamentals means you’re less likely to accidentally ship something fragile.

Which brings us to this rather quaint little exercise: building a Rock-Paper-Scissors CLI game in TypeScript. Now, before you dismiss this as child’s play, remember the first rule of coding: the simple stuff often hides the most insidious bugs if you don’t lay down a solid foundation. And that’s precisely what this project, penned by a self-proclaimed Java engineer taking their second stab at TypeScript, aims to do.

Why Bother With a CLI Game?

Look, we’re not talking about the next big crypto exchange here. This is a command-line interface, a bit of digital Tic-Tac-Toe for programmers. But the author’s intent is clear: to get a grip on core TypeScript features like union types and conditional logic, all while wrestling with a testing framework – this time, Jest, after a previous encounter with Vitest. It’s a learning journey, and the messy bits are often the most illuminating.

And honestly, who’s actually making money here? Not the author, certainly. They’re spending their own time, their own cash (on Claude Pro and Cursor Pro, no less) to figure this stuff out. This is pure, unadulterated learning for the sake of understanding. That’s the kind of raw effort we appreciate here at Open Source Beat.

The Code, In Brief

The project is structured neatly, a good sign. We’ve got files for the entry point (index.ts), game logic (game.ts), type definitions (types.ts), and the obligatory tests (game.test.ts). It’s a clean separation of concerns, which, if you’ve been around the block more than a decade, you know is the bedrock of maintainable code.

At the heart of it are these type definitions:

export type Hand = 'rock' | 'paper' | 'scissors';
export type Result = 'win' | 'lose' | 'draw';

Union types. Why not an enum? The author points out that union types offer cleaner logs, which is a fair point when you’re debugging. String literals just read better than a cryptic 0, 1, or 2. And they’ve correctly exported them, understanding that these types will be needed elsewhere. Good.

The Logic: Where Things Get Interesting (or Not)

The determineResult function is where the core game logic lives. It’s a classic scenario for conditional branching.

```typescript export function determineResult(player: Hand


🧬 Related Insights

Written by
Open Source Beat Editorial Team

Curated insights, explainers, and analysis from the editorial team.

Worth sharing?

Get the best Open Source stories of the week in your inbox — no noise, no spam.

Originally reported by Dev.to

Stay in the loop

The week's most important stories from Open Source Beat, delivered once a week.