I recently wrote about
Here's the definition:
Or, a one-liner:
Now, you're probably thinking to yourself: "That's a silly function! It just calls a function." And yes,
run is simple, but its deceptively useful too.
run has two primary use cases:
Lets look at some examples.
1. Use as an IIFE
When acting like an IIFE,
run takes a sync or async function and...runs it! To my eyes, the version with
run is cleaner.
2. Use as a
Unfortunately, this proposal is a few years old and seems stale. Fortunately, we can get almost all of the benefit of
do expressions with
When acting like a
run executes a function and returns its value, which brings with it all the benefits of early returns via
else statements without needing to extract the function out of its parent function context.
This is handy for a few reasons:
- Inline early returns
- Simple variable assignment
- Receive parent scope
- Don't need to declare and name a function
Use in Templating Languages
do-like expressions are especially helpful in templating languages like JSX where there is conditional logic requiring
And, let me be clear: multi-line ternary operators are bad. Nobody wants ternary hell. Long ternaries are unreadable and hard to refactor, and I see them all the time in React projects.
Wouldn't this be nice to use in your next frontend project?
And now you might be thinking "but why not just make that another component?". And sure, you could do that, and in some cases it makes absolute sense to do that.
But, in many cases, your complex conditional rendering does not need to be abstracted into new components. Instead, you can break the pieces of rendering into logical
run functions. This removes the need to make largely useless display components just to benefit from early returns.
Advanced Use Case: Promises
When working with Promises,
run makes more sense than
do because it doesn't use the
async scope of the parent and instead allows you to create and execute
async functions inline.
Let's say we are writing a deploy script, and we are deploying two things at once: 1) a dockerized server and 2) lambda functions. In this case,
run can be used to build and deploy both at the same time while maintaining parent scope.
run returns the result of running the function it is passed. When passed an
async function, it will return a
In my most recent project, I used
run over 300 times in a variety of circumstances. I used it everywhere: bin scripts, backend code, and frontend code. I love how
run makes my code more readable and functional. And, if you use TypeScript,
run is the best for ripping apart discriminated unions and getting the correct type inference. Try it once and you'll be hooked! (
run is also useful in hooks like
useMemo but that was just a figure of speech)
I hope that this simple utility will catch on so we can stop using nested ternaries and simplify complex async operations. If you agree, spread the word by sharing this post!
Q: "Max, will you make this into an
npm package? That would be really handy!"
A: No, its one line. That wouldn't make any sense. Ready, copy, paste!