- Ternary expressions are ugly and even more so when nested.
- Solutions like lodash.cond have unnecessary function invocation overhead and are less readable. To ensure lazy evaluation we need to wrap each branch in function.
This utility is implemented as a babel-macro.
npm install --save-dev babel-plugin-macros if-exprmacro
- Add babel-plugin-macros to .babelrc (if not already preset):
// .babelrcmoduleexports =presets:// ... other presetsplugins:'babel-plugin-macros' // <-- REQUIRED// ... other plugins;
if-expr.macroin your code:
// src/foo.js;const result = ;
- Branches are evaluated lazily
const result =;// result is what someFn returns// someOtherFn is never called
- then/else branches are optional
const result = ;// someFn is never called// result is undefined
- Multiple then/else branches are allowed:
const result =;// Both someFn and someOtherFn are called// result is what someOtherFn returns
const result =;// Only someOtherFn is called// result is what someOtherFn returns
- Side-effect only branches:
;// All of the functions are called (in specified order), but their return values are discareded// The expression evaluates to undefined
- Side-effect only branches can be combined with then/else branches:
const result =;// result is what someFn returns// returned value (if any) of someOtherFn is discarded
Usage with TypeScript
This library is type-safe and comes with type definitions.
All code must be processed through babel. Compilation through tsc (only) is not supported.
Recommended babel configuration:
// .babelrcmoduleexports =presets:'@babel/preset-typescript'// ... other presetsplugins:'babel-plugin-macros'// ... other plugins;
Flow based type inference
One caveat is that TypeScript's flow-based type inference will not treat
.else branches same as normal
const a: undefined | string = ;if a; // Not an error because TypeScript is smart enough to know// that a can not be undefined in this branch
const a: undefined | string = ;|________|// We need to identify -. ^// a as a string to |------------/// prevent type error -'
AFAIK, currently there is no workaround for feasible.
Every If/then/else chain fluent must end with a final function invocation without interruptions.
const a = 10;const intermediate = ;const result = ;
Above code will fail to compile.
Because the entire If/then/else chain is compiled away, anything return by If/then/else can not be assigned, referenced, or used in any computation.
You may also like:
- switch-expr.macro: Similar utility, providing a fluent expression-oriented macro replacement for switch statement