Javascript is disabled which is ok, but some features may not work properly. Explaining the video "Enums Considered Harmful" of Matt Pocock Explaining the video “Enums Considered Harmful” of Matt Pocock | Fredy.dev A blog about programming

Explaining the video "Enums Considered Harmful" of Matt Pocock

Posted on December 18, 2022.

I was watching this video by Matt Pocock, but I found really hard to digest and internalize the TypeScript, so I decided to create a little guide, because I learn better when I explain things to others, so here it is. The TypeScript shown in the video

const LOG_LEVEL = {
   DEBUG: 'debug',
   WARNING: 'warning',
   ERROR: 'error',
} as const;

type ObjectValues<T> = T[keyof T];
type LogLevel = ObjectValues<typeof LOG_LEVEL>



Destructuring…

‘typeof’ will get you the types

type LOG_LEVEL_TYPE = typeof LOG_LEVEL;
// Hardcoded will be like this:
type LOG_LEVEL_TYPE_2 = {
    readonly DEBUG: "debug";
    readonly WARNING: "warning";
    readonly ERROR: "error";
}

‘keyof’ will get the keys

type LOG_LEVEL_KEYS = keyof LOG_LEVEL_TYPE;
// Hardcoded will be like this:
type LOG_LEVEL_KEYS_2 = "ERROR" | "WARNING" | "DEBUG"

‘type[i]’ will get the values

type LOG_LEVEL_VALUES = LOG_LEVEL_TYPE["ERROR" | "WARNING" | "DEBUG"];
// or
type LOG_LEVEL_VALUES_2 = LOG_LEVEL_TYPE[LOG_LEVEL_KEYS];
// Hardcoded will be like this:
type LOG_LEVEL_VALUES_3 = "debug" | "warning" | "error"

For example the variable myLog can only be the VALUES, anything else will throw an error

let myLog: LOG_LEVEL_VALUES;
myLog = 'debug';
myLog = 'warning';
myLog = 'error';

MyLog_2 can only be the KEYS

let myLog_2: LOG_LEVEL_KEYS;
myLog_2 = 'DEBUG';
myLog_2 = 'ERROR';
myLog_2 = 'WARNING';

The previous can also be compressed and written like this:

type LOG_LEVEL_VALUES_4 = typeof LOG_LEVEL[keyof typeof LOG_LEVEL];
// Hardcoded will be like this:
type LOG_LEVEL_VALUES_5 = "debug" | "warning" | "error"



Now explaining the TypeScript will be:

type ObjectValues<T> = T[keyof T];

// Imagine it as a function that returns the values of wherever T is.
function ObjectValues(T:any) {
    return T[Object.keys(T)[0]]
}

for example:

type MyType = {
   myString: 'my string',
   myNumber: 23,
}

let myValue:ObjectValues<MyType>;
myValue = 'my string' // can only be the litteral string,
myValue = 23;         // or the litteral value

Explaining the last part

type LogLevel = ObjectValues<typeof LOG_LEVEL>
// Now imagine this part like we actually execute the function and 
// we passed the types provided by "typeof"
let logLevel = ObjectValues({ myString: 'my string'})

Playground Link