potato face
CryingPotato

Exhaustive Matching in Typescript #

When working in Typescript I miss the exhaustive match statements I’ve gotten used to in Rust. They’re super useful when dealing with Enums and expansive types that you want to make sure you cover all cases for. When working on Cannon I have an enum defined for a language. Along the way I discovered a couple of nifty tricks for exhaustive case matching in Typescript. The simple way is to have an exhaustive object:

enum Language {
	Python = 'python',
	Java = 'java'
}

type LanguageMap<T> = { [language: Language]: T}

const a: LanguageMap<number> = {
	[Langauge.Python]: 0,
}

If you have an unreasonable affinity for switch statements like I do, you can do this instead:

enum Language {
	Python = 'python',
	Java = 'java'
}

export function assertUnreachable(_: never): never;
export function assertUnreachable(_: Language) {
  throw new Error('Unreachable');
}

function a(l: Language): number {
	switch(l) {
		case Language.Python:
			return 0;
		default:
			assertUnreachable(l);
	}
}

which I think is really nifty. Credit to this StackOverflow answer!