Do Notation

A do notation syntax allows writing code in a more declarative style, similar to the do notation in other programming languages. It provides a way to define variables and perform operations on them using functions like bind and let, piping the returned values into a context object.

Do

Initiates a Do-notation for the AsyncOption type.

import { AsyncOption } from 'funkcia';

declare function findUserById(id: string): AsyncOption;
declare function calculateUserScore(user: User): AsyncOption;
declare function rankUserLevel(user: User, score: UserScore): AsyncOption;

//        β”Œβ”€β”€β”€ AsyncOption
//        β–Ό
const userLevel = AsyncOption.Do
  .bind('user', () => findUserById('user_123'))
  .bind('score', (ctx) => calculateUserScore(ctx.user))
  .andThen((ctx) => rankUserLevel(ctx.user, ctx.score));
//           β–²
//           └─── { user: User; score: UserScore }

bindTo

Initiates a Do-notation with the current AsyncOption, binding it to a context object with the provided key.

bind

Binds an AsyncOption to the context object in a Do-notation.

If the AsyncOption resolves to Some, the value is assigned to the key in the context object. If the AsyncOption resolves to None, the parent AsyncOption running the Do simulation becomes a None.

let

Binds a non-rejecting promise to the context object in a do notation.

If the promise resolves to a non-nullable value, the value is assigned to the key in the context object. If the promise resolves to null or undefined, the parent AsyncOption running the Do simulation becomes a None.

Understanding the do notation

Do notation provides a clean way to handle sequences of operations that might fail, where each step depends on the success of all previous steps. Think of it as a chain of dominoes - if any domino falls incorrectly (resolves to Option.None), the entire sequence stops.

Here's a practical example:

The equivalent code would be much more nested:

Or with intermediate variables:

Last updated

Was this helpful?