operator ~ method

dynamic operator ~()

Shortcut for propagateResultAsync.

Usage:

// This function will error at runtime if passed an Err() value
Future<Result<int, String>> add(Result<int, String> a, Result<int, String> b) async {
  return Ok(a.unwrap() + b.unwrap());
}

// For safety, it can be rewritten as:
Future<Result<int, String>> add(Result<int, String> a, Result<int, String> b) => ~() async {
  return Ok(a.unwrap() + b.unwrap());

  // You can also use the ~ operator as a shortcut for unwrap():
  // return Ok(~a + ~b);
};

// Runtime safety achieved from a mere 8 total characters of syntactical overhead!

Note: This operator returns dynamic. Consider explicitly typing receivers of this operation to limit the amount of dynamic being passed around in your codebase.

If this operator were typed to return Future<Result<T, E>> and you were to return Ok() or Err() in the prefixed function, the compiler would treat the operator as returning Future<Result<T, dynamic>> or Future<Result<dynamic, E>>.

Operators are not able to receive generic type parameters and thus this operator is unable to infer the generic types of the returned Result in the same way propagateResult can.

// Compiles fine
Result<int, String> foo = await propagateResultAsync(() async => Ok(1));

// If this operator were typed to return Future<Result<T, E>>:

// Error: A value of type 'Result<int, dynamic>' can't be assigned to a variable of type 'Result<int, String>'
Result<int, String> bar = await ~() async => Ok(1);

// The only way around this would be to explicitly specify the type parameters
// on the returned result like:
Result<int, String> baz = await ~() async => Ok<int, String>(1);

// And that's not very ergonomic when you are already likely to type your
// variables and function/method returns

Hence, this operator returns dynamic to avoid this problem. The compiler will still enforce returning Result values regardless, as this operator is only provided for functions which return Result.

If a dynamic return value is undesireable to you, consider using propagateResultAsync directly instead.

Implementation

operator ~() => propagateResultAsync(this);