Type-Level Hangman in TypeScript
- Published On
- Read Time
- 1 min
You can actually implement Hangman in TypeScript at the type level. Your guessed letters are represented as a type, and the result is also a type. There’s no runtime code - just pure type manipulation.

It may not look exactly like classic Hangman, since TypeScript doesn’t support displaying multi-line template literal types. Instead, we use a single-line emoji visualization.
How many languages let you do this? TypeScript is impressive!
Implementation
And here’s the code. Open this in the TypeScript Playground and the ^? will show you the result type directly inline.
type Input = ""; // <-- Enter your guessed letters here
type X = Guess<Input>;
// ^?
// ------------------------------------------------------------------------
type Guess<T extends string> = `${GameLetters<T>} => ${GameState<T>}`;
type GameLetters<TGuess extends string> = Letters<GameSolution, LettersOf<Uppercase<TGuess>>>;
type GameState<TGuess extends string> = Drawing<NumberOfWrongGuesses<LettersOf<GameSolution>, Uppercase<TGuess>>>;
type LettersOf<T extends string> = T extends `${infer TLetter}${infer TRest}` ? TLetter | LettersOf<TRest> : never;
type Letters<TWord extends string, TGuessedLetters extends string> = TWord extends `${infer TLetter}${infer TRest}`
? `${TLetter extends TGuessedLetters ? TLetter : "_"}${Letters<TRest, TGuessedLetters>}`
: "";
type NumberOfWrongGuesses<
TWordLetters extends string,
TGuess extends string,
TStrikes extends string[] = [],
> = TGuess extends `${infer TLetter}${infer TRest}`
? NumberOfWrongGuesses<
TWordLetters,
TRest,
TLetter extends TWordLetters ? TStrikes : TLetter extends TStrikes[number] ? TStrikes : [...TStrikes, TLetter]
>
: TStrikes["length"];
type Drawing<TIndex extends number> = Drawings[TIndex] extends undefined ? LastOf<Drawings> : Drawings[TIndex];
type Drawings = ["🥳______", "🥳_____💣", "😐____💣", "☹️___💣", "😦__💣", "😵_💣", "😱💣", "☠️"];
type LastOf<T> = T extends [...infer _, infer TLast] ? TLast : never;
type GameSolution = Uppercase<"TypeScript">;