Last active
September 8, 2019 15:38
-
-
Save lindekaer/6ba963939a2ec4c4d4f8355a1d781298 to your computer and use it in GitHub Desktop.
Exhaustive checking in Typescript
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Exhaustive checking is the concept of ensuring that all possibilities have | |
been covered when e.g. handling the different cases for values in an enum. | |
Below are some snippets to achieve this in Typescript. | |
*/ | |
enum Job { | |
Engineer = 'engineer', | |
KeyAccountManager = 'key-account-manager', | |
StudentAssistant = 'student-assistant', | |
Marketeer = 'marketeer' | |
} | |
// SOLUTION 1: Throw a `never` error | |
function exhaustiveCheck( param: never ): never { | |
throw new Error( 'should not reach here' ) | |
} | |
const getSalary = (job: Job) => { | |
switch (job) { | |
case Job.Engineer: return 100 | |
case Job.KeyAccountManager: return 85 | |
case Job.StudentAssistant: return 25 | |
default: return exhaustiveCheck(job) | |
} | |
} | |
// SOLUTION 2: Assign and return `never` type | |
const getSalary2 = (job: Job) => { | |
switch (job) { | |
case Job.Engineer: return 100 | |
case Job.KeyAccountManager: return 85 | |
case Job.StudentAssistant: return 25 | |
default: { | |
const _exhausted: never = job | |
return job | |
} | |
} | |
} | |
// SOLUTION 3: Run TS with -strictNullChecks flag | |
function getSalary3(job: Job): number { // error: returns number | undefined | |
switch (job) { | |
case Job.Engineer: return 100 | |
case Job.KeyAccountManager: return 85 | |
case Job.StudentAssistant: return 25 | |
} | |
} | |
// SOLUTION 4: Custom function iterating the enum | |
export function exhaustSwitch<T extends string, TRet>( | |
value: T, | |
map: { [x in T]: () => TRet } | |
): TRet { | |
return map[value](); | |
} | |
exhaustSwitch('marketeer' as Job, { | |
[Job.Engineer]: () => 100, | |
[Job.KeyAccountManager]: () => 85, | |
[Job.StudentAssistant]: () => 25, | |
}); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment