What if you could write something like:
const value = switch (query) {
case candidate1:
optionA;
case candidate2:
optionB;
default:
optionC;
};
Enter, cont-flow-expr.switch
:
import hctiws from "cont-flow-expr.switch";
const value = hctiws(query)
.case(candidate1).then(optionA)
.case(candidate2).then(optionB)
.default(optionC);
A switch-case
expression can be written as:
import hctiws from "cont-flow-expr.switch";
const value = hctiws(query)
.case(candidate1).then(optionA)
.case(candidate2).then(optionB)
// .case(candidateN-1).then(optionN-1)
.default(optionZ);
with arbitrarily many uses of .case().then()
.
Branches can also be evaluated lazily:
import hctiws from "cont-flow-expr.switch";
const value = hctiws(query)
.case(candidate1).thenDo(() => optionA)
.case(candidate2).thenDo(() => optionB)
.defaultDo(() => optionC);
Normal and lazy branches can be mixed arbitrarily, for example:
import hctiws from "cont-flow-expr.switch";
const value = hctiws(query)
.case(candidate1).thenDo(() => optionA)
.case(candidate2).then(optionB)
.default(optionC);
Fallthrough is supported but has to be done explicitly, for example:
import hctiws from "cont-flow-expr.switch";
const value = hctiws(query)
.case(candidate1).thenDoFallthrough(() => fn())
.case(candidate2).then(optionA)
.default(optionB);
// is the same as
let value;
switch (query) {
case candidate1:
fn();
case candidate2:
value = optionA;
break;
default:
value = optionB;
}
Cases can be evaluated lazily by using .caseLazy()
, for example:
import hctiws from "cont-flow-expr.switch";
const value = hctiws(query)
.case(candidate1).then(optionA)
.caseLazy(() => candidate2).then(optionB) // not run if `query` matches `candidate1`
.default(optionC);
TypeScript support is included and can be used to ensure all branches evaluate to the same type (union). Type parameters are required for this to work. For example:
import hctiws from "cont-flow-expr.switch";
const query = 3.14, candidate1 = 3, candidate2 = 14;
const optionA = "foo", optionB = "bar", optionC = "baz", optionD = 42;
// Works
const aString = hctiws<number, string>(query)
.case(candidate1).then(optionA)
.case(candidate2).then(optionB)
.default(optionC);
// Fails
const fails = hctiws<number, string>(query)
.case(candidate1).then(optionA)
.case(candidate2).then(optionB)
.default(optionD);
// ~~~~~~~> TypeError:
// Argument of type 'number' is not assignable to parameter of type 'string'.
// Works
const aStringOrNumber = hctiws<number, string | number>(query)
.case(candidate1).then(optionA)
.case(candidate2).then(optionB)
.default(optionD);
The benchmarks in this project - which are powered by Benchmark.js - can be used to compare this library against vanilla JavaScript as well as alternative libraries. Here's a sample result:
vanilla x 1,411,831,771 ops/sec ±0.15% (98 runs sampled)
cont-flow-expr x 15,601,299 ops/sec ±0.83% (94 runs sampled)
-
cont-flow-expr.if
- If statements as expressions. -
cont-flow-expr.try
- Try statements as expressions. -
cont-flow-expr
- Combines this and all of the above into one convenient package.
The source code is licensed under the ISC license. The documentation text is licensed under CC BY 4.0.