-
-
Save nash403/a248697941b5b5be970d9658f32197ff to your computer and use it in GitHub Desktop.
My preferred way of handling try/catch 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
// Types for the result object with discriminated union | |
type Success<T> = { | |
data: T; | |
error: null; | |
}; | |
type Failure<E> = { | |
data: null; | |
error: E; | |
}; | |
type Result<T, E = Error> = Success<T> | Failure<E>; | |
type MaybePromise<T, Args extends any[]> = ((...args: Args) => T) | Promise<T>; | |
// Main wrapper function | |
async function tryCatch<T, Args extends any[], E = Error>( | |
input: MaybePromise<T, Args>, | |
...args: Args | |
): Promise<Result<T, E>> { | |
try { | |
// Check if input is a function (sync case) and call it with arguments, otherwise assume it's a Promise | |
const data = await Promise.resolve( | |
typeof input === "function" ? input(...args) : input | |
); | |
return { data, error: null }; | |
} catch (error) { | |
return { data: null, error: error as E }; | |
} | |
} |
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
// see TS this playground https://www.typescriptlang.org/play/?ssl=14&ssc=13&pln=2&pc=13#code/PTAEBUE8AcFMGdQDMD2AnUAXAFrUaEBXAG01BQCMArWAYzIHcBLHUAEyflrSYFsmAdgENMsNqEICmKAQCgQWGHgDKhWrQTwAPOAB8oALygA3vLCh2IoQC4IAbjMXQsNGnS2BJYg4UBfB46YSqAAYkJMxIQEWgCi+kamChZsVh5ePubOru6gMRmg-rKBwQBKRKQ6ADS5hrnZaPGgquqaOvoAPqHhkdFxAQpBcKAAskKQFLAACm788LBttQAUiwCUhvrga53TKLOwADJMANbzev1go4KgDGhC0HAYSJL00nIKQvCQArTIz5ivWDQkAAwiJaNgqjUjDF6rpFo4LNAZpxYLYdns2pVHCs0ci5loyvASJhIXF9IlMpggSYEU5aDJ4GQUpghLUhAxwmQkbsUfknPhYJgogITJYWdUXG40GliMQCnyCqBaGDsKBFpL0GsKfyBUK0CLjGKbKBPLKJfVbBqMB8aoUkgVHL4igp6QJGYCQSraqTajCpXDaUgBLiefi9KBOss1gYNissQocaBCcTSR1QOiUQTyiTwNUyesafamEg1YNYCgS0HDAYjAAiJ7ff4yWta2kWKmQQuZfmu93M1lGRZVm2rAubVYK-kEPUGo3mqUyuV27uK5WYcFqq2t+1TwXC0X9xfznJW0A2mLytsO+1O2nT-dDkU2jNh3QrK8AOhwsAEy370f0RZDX7Y9pRNLwChWd8d1AD813BZYtwLICjSPLIF3Q9Az0QC9fCg-JCmdMAPi+H4GxeGQPVBdcIVzKE6n9eEiwEaBCEwWxRnGKY8VOXRsRDDFkwqOj821dtqTEpwFGBXBaCOUBiwUli2IUxBWXIpsRUWT5viVD5YDjchvzQZg5mwoleDwFgAHI1PTHir17JkrDZDkWHs0NYA-Ah4BQYgADdYCYld2yUCslNYsgazrDTXlrUAAH41UESLsLVACIBWUdbBStirxWc4dXvfUDysUDF0vG89Jozd6m3FditnQ9wLNTCwNPc9KsyJ0-CKRwoDgRBUAwb8BSJUhyGoOhGBYVUOC4Hh+GEURxEkV5ZDLJo1A0eBtHDBJZGSVJ7EOtrFwcQjNrCCIonmOJalMI6WXO06rVsPJZEu0psx9aFYVqZodr2tNrp6O7dACTbOImF9TmqABBNAAHNEFgAAPUQBDYNSBEgABtABdRplg-UmhGR+BbERlGMs2CMPIxM4iJGcIRRuO4Hl+Rt1pI3TYsojtqPBSFqdRjGf2xs9ccJvNfVheELFy9iWa42GRYp3QsQsUmP3JlGqYp2REzVoSczzXRyVOjsaX5aTZPkxSldUs8uYorSdJ+ZU5jWIQsb02UFJm1g9cISyBEweBqhQYzTLwD4LKszBbJd2HTosJyjVczkGZRbyED8wKFZ1Mtwqd6LQHrP44sSiK2MWHW9fgNYcuUzA09AAqil3GdSvFM6WqXBwLF8aqN3VOqbacRre+NU1iHKtq0twoeHVvXmyKryi2BQUYcHhj3R0eukGTIfyhEiPAjF37BvN97feFWLunEUxYz4v0B9AABg-ABWNYcDcAwE0sAgF+nQIsaymAUAoFAMQPWsBrLvnbtPWGedfIBSCm-QgBlPpFH5iKbe19Fiz1DhMDARhP6th7CfUAWDL4sxwLfLGuxRwAGozxP0ViWV+59sGgC0KAb+f8sDYEAcA0B9QIFQJgXA5GCCkHd33HQ3Bsh16u00sgQU4IAAiVhFhMDYGkXgZDjY8S0IyHgAgkaWy4clcQ5dKEiLEQIEBDFwG1gAJICDfgY0AHjtEthXtPAABrolkyAsL+NAAAEmMAY3wwSLpFGIR7dKBYj7pxocBMqi9FRGHZNnQWKpFiEJENgfepF3zULdH5LyxAUBIwgejfAd9sKkWQMGay1QQJtXfHhCcyS1GjhjJPTJboyDZL7qePJZ43JkCKTRKMBZSk4FWFU4+NTiB1IaU0tGLS-apKDNYLpc5emfSyp3WQKT2nDJsRs90kyhCgWHlndyCyEIrOwOssZ6DtmNOss024Bz2lVgIEgY53SclbnOQMq5QyMoZKVFk050yR75LmVRYpnzqgACZvlIs2X83Z+zxCHJFGC64s0zwUwhSiuqMLLnXN0rc0ZBKHl0qlC89FhSgRC2wEOLR2AwlPNAAAZlFfi3stSPz1P+c0tRVZmDBxpScnp0L+mMvhek9uGdHnPJmQUt5vLilIEFcK6olCdUMmlbK4lCq2ZUsbsgbotK1X0o1QEJlPwWWIt1RyrCBqMXvP5agnyBcgq1mULsPAwqWySutVsmVOyAV7O5HsMa4bXVQvdRcz1WqRm+uRW6zlgaeWekWaG2ANB6CLEjdGtxaA41WsJUmuVqaeICmrexVV2apR9NzUAA | |
async function doMathAsync() { | |
const value = Math.random() | |
if (value > 0.5) throw new Error('too large') | |
return Promise.resolve(value) | |
} | |
function doMath(a: number = 0) { | |
const value = Math.random() + a | |
if (value < 0.5) throw new Error('too large') | |
return value | |
} | |
async function fetchData(id: number): Promise<string> { | |
if (id === 0) throw new Error("Invalid ID"); | |
return `Data for ID ${id}`; | |
} | |
(async () => { | |
const { data, error } = await tryCatch(doMathAsync) | |
console.log('ex rand async fn:', data, error) | |
})(); | |
(async () => { | |
const { data, error } = await tryCatch(() => doMath()) | |
console.log('ex rand sync fn:', data, error) | |
})(); | |
(async () => { | |
const { data, error } = await tryCatch(doMath) | |
console.log('ex rand sync fn ref:', data, error) | |
})(); | |
(async () => { | |
const { data, error } = await tryCatch(doMath, 2) | |
console.log('ex rand sync fn ref with args:', data, error) | |
})(); | |
(async () => { | |
const { data, error } = await tryCatch(fetchData, 33) | |
console.log('ex async fn with args:', data, error) | |
})(); | |
(async () => { | |
const { data, error } = await tryCatch(fetchData, 0) | |
console.log('ex async fn with args fail:', data, error) | |
})(); | |
(async () => { | |
const { data, error } = await tryCatch(Promise.resolve("Some Data")) | |
console.log('ex promise resolve:', data, error) | |
})(); | |
(async () => { | |
const { data, error } = await tryCatch(Promise.reject("Some Error")) | |
console.log('ex promise reject:', data, error) | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment