Advanced TypeScript #6: reverse map enums
Here’s part 6 of 7 of the Advanced TypeScript series, where I share TypeScript patterns I’ve encountered in enterprise grade applications.
6. Enum values to keys reverse mapping
This is a trick more than something you should use often. I would leave a comment explaining how/why code using this behaviour works because it's non obvious (a lot of people are unaware of this feature).
A place where this is particularly useful is with protobuf definitions whose labels codegen to enums with numeric values.
enum PaymentType {
CC = 1,
BACS = 2,
}
enum Platform {
WEB,
MOBILE,
}
enum PlatformStringValues {
WEB = 'web',
MOBILE = 'mobile',
}
const paymentType = PaymentType.CC;
const platform = Platform.MOBILE;
const platformString = Platform.WEB;
import { expectTypeOf } from 'expect-type';
import assert from 'node:assert';
import test from 'node:test';
test('reverse mapping of enum with set numeric values', () => {
assert.equal(PaymentType[paymentType], 'CC');
});
test('reverse mapping of enum with implicit numeric values', () => {
assert.equal(Platform[platform], 'MOBILE');
});
test('reverse mapping of enum with string values - does not work', () => {
expectTypeOf(PlatformStringValues).not.toHaveProperty(platformString);
// @ts-expect-error
// Element implicitly has an 'any' type because expression of type 'Platform.WEB' can't be used to index type 'typeof PlatformStringValues'.
// Property '[Platform.WEB]' does not exist on type 'typeof PlatformStringValues'
assert.equal(PlatformStringValues[platformString], undefined);
});
You can read more in the docs: https://www.typescriptlang.org/docs/handbook/enums.html#reverse-mappings
That's this week's pattern, you can get a sneak peek of the rest at codewithhugo.com/typescript-types-in-the-trenches/, or access the annotated source at github.com/HugoDF/real-world-ts.