diff --git a/src/ErrorOr.cs b/src/ErrorOr.cs index b174eba..9f317eb 100644 --- a/src/ErrorOr.cs +++ b/src/ErrorOr.cs @@ -276,6 +276,22 @@ public ErrorOr Then(Func> onValue) return onValue(Value); } + /// + /// If the state is a value, the provided function is executed and its result is returned. + /// + /// The type of the result. + /// The function to execute if the state is a value. + /// The result from calling if state is value; otherwise the original . + public ErrorOr Then(Func onValue) + { + if (IsError) + { + return Errors; + } + + return onValue(Value); + } + /// /// If the state is a value, the provided function is executed asynchronously and its result is returned. /// @@ -292,6 +308,22 @@ public async Task> ThenAsync(Func + /// If the state is a value, the provided function is executed asynchronously and its result is returned. + /// + /// The type of the result. + /// The function to execute if the state is a value. + /// The result from calling if state is value; otherwise the original . + public async Task> ThenAsync(Func> onValue) + { + if (IsError) + { + return Errors; + } + + return await onValue(Value).ConfigureAwait(false); + } + /// /// If the state is error, the provided function is executed and its result is returned. /// diff --git a/src/ErrorOrExtensions.cs b/src/ErrorOrExtensions.cs index cf53993..b4ef7d3 100644 --- a/src/ErrorOrExtensions.cs +++ b/src/ErrorOrExtensions.cs @@ -17,6 +17,21 @@ public static async Task> Then(this T return result.Then(onValue); } + /// + /// If the state of is a value, the provided function is executed and its result is returned. + /// + /// The type of the result. + /// The type of the next result. + /// The error. + /// The function to execute if the state is a value. + /// The result from calling if state is value; otherwise the original errors. + public static async Task> Then(this Task> errorOr, Func onValue) + { + var result = await errorOr.ConfigureAwait(false); + + return result.Then(onValue); + } + /// /// If the state of is a value, the provided function is executed asynchronously and its result is returned. /// @@ -32,6 +47,21 @@ public static async Task> ThenAsync(t return await result.ThenAsync(onValue).ConfigureAwait(false); } + /// + /// If the state of is a value, the provided function is executed asynchronously and its result is returned. + /// + /// The type of the result. + /// The type of the next result. + /// The error. + /// The function to execute if the state is a value. + /// The result from calling if state is value; otherwise the original errors. + public static async Task> ThenAsync(this Task> errorOr, Func> onValue) + { + var result = await errorOr.ConfigureAwait(false); + + return await result.ThenAsync(onValue).ConfigureAwait(false); + } + /// /// If the state is error, the provided function is executed asynchronously and its result is returned. /// diff --git a/tests/ErrorOr.MatchAsyncTests.cs b/tests/ErrorOr.MatchAsyncTests.cs index 4d9248e..9cff8db 100644 --- a/tests/ErrorOr.MatchAsyncTests.cs +++ b/tests/ErrorOr.MatchAsyncTests.cs @@ -1,98 +1,98 @@ -using ErrorOr; -using FluentAssertions; - -namespace Tests; - -public class MatchAsyncTests -{ - private record Person(string Name); - - [Fact] - public async Task MatchAsyncErrorOr_WhenHasValue_ShouldExecuteOnValueAction() - { - // Arrange - ErrorOr errorOrPerson = new Person("Amichai"); - Task OnValueAction(Person person) - { - person.Should().BeEquivalentTo(errorOrPerson.Value); - return Task.FromResult("Nice"); - } - - Task OnErrorsAction(IReadOnlyList _) => throw new Exception("Should not be called"); - - // Act - var action = async () => await errorOrPerson.MatchAsync( - OnValueAction, - OnErrorsAction); - - // Assert - (await action.Should().NotThrowAsync()).Subject.Should().Be("Nice"); - } - - [Fact] - public async Task MatchAsyncErrorOr_WhenHasError_ShouldExecuteOnErrorAction() - { - // Arrange - ErrorOr errorOrPerson = new List { Error.Validation(), Error.Conflict() }; - Task OnValueAction(Person _) => throw new Exception("Should not be called"); - - Task OnErrorsAction(IReadOnlyList errors) - { - errors.Should().BeEquivalentTo(errorOrPerson.Errors); - return Task.FromResult("Nice"); - } - - // Act - var action = async () => await errorOrPerson.MatchAsync( - OnValueAction, - OnErrorsAction); - - // Assert - (await action.Should().NotThrowAsync()).Subject.Should().Be("Nice"); - } - - [Fact] - public async Task MatchFirstAsyncErrorOr_WhenHasValue_ShouldExecuteOnValueAction() - { - // Arrange - ErrorOr errorOrPerson = new Person("Amichai"); - Task OnValueAction(Person person) - { - person.Should().BeEquivalentTo(errorOrPerson.Value); - return Task.FromResult("Nice"); - } - - Task OnFirstErrorAction(Error _) => throw new Exception("Should not be called"); - - // Act - var action = async () => await errorOrPerson.MatchFirstAsync( - OnValueAction, - OnFirstErrorAction); - - // Assert - (await action.Should().NotThrowAsync()).Subject.Should().Be("Nice"); - } - - [Fact] - public async Task MatchFirstAsyncErrorOr_WhenHasError_ShouldExecuteOnFirstErrorAction() - { - // Arrange - ErrorOr errorOrPerson = new List { Error.Validation(), Error.Conflict() }; - Task OnValueAction(Person _) => throw new Exception("Should not be called"); - Task OnFirstErrorAction(Error errors) - { - errors.Should().BeEquivalentTo(errorOrPerson.Errors[0]) - .And.BeEquivalentTo(errorOrPerson.FirstError); - - return Task.FromResult("Nice"); - } - - // Act - var action = async () => await errorOrPerson.MatchFirstAsync( - OnValueAction, - OnFirstErrorAction); - - // Assert - (await action.Should().NotThrowAsync()).Subject.Should().Be("Nice"); - } -} +using ErrorOr; +using FluentAssertions; + +namespace Tests; + +public class MatchAsyncTests +{ + private record Person(string Name); + + [Fact] + public async Task MatchAsyncErrorOr_WhenIsSuccess_ShouldExecuteOnValueAction() + { + // Arrange + ErrorOr errorOrPerson = new Person("Amichai"); + Task OnValueAction(Person person) + { + person.Should().BeEquivalentTo(errorOrPerson.Value); + return Task.FromResult("Nice"); + } + + Task OnErrorsAction(IReadOnlyList _) => throw new Exception("Should not be called"); + + // Act + var action = async () => await errorOrPerson.MatchAsync( + OnValueAction, + OnErrorsAction); + + // Assert + (await action.Should().NotThrowAsync()).Subject.Should().Be("Nice"); + } + + [Fact] + public async Task MatchAsyncErrorOr_WhenIsError_ShouldExecuteOnErrorAction() + { + // Arrange + ErrorOr errorOrPerson = new List { Error.Validation(), Error.Conflict() }; + Task OnValueAction(Person _) => throw new Exception("Should not be called"); + + Task OnErrorsAction(IReadOnlyList errors) + { + errors.Should().BeEquivalentTo(errorOrPerson.Errors); + return Task.FromResult("Nice"); + } + + // Act + var action = async () => await errorOrPerson.MatchAsync( + OnValueAction, + OnErrorsAction); + + // Assert + (await action.Should().NotThrowAsync()).Subject.Should().Be("Nice"); + } + + [Fact] + public async Task MatchFirstAsyncErrorOr_WhenIsSuccess_ShouldExecuteOnValueAction() + { + // Arrange + ErrorOr errorOrPerson = new Person("Amichai"); + Task OnValueAction(Person person) + { + person.Should().BeEquivalentTo(errorOrPerson.Value); + return Task.FromResult("Nice"); + } + + Task OnFirstErrorAction(Error _) => throw new Exception("Should not be called"); + + // Act + var action = async () => await errorOrPerson.MatchFirstAsync( + OnValueAction, + OnFirstErrorAction); + + // Assert + (await action.Should().NotThrowAsync()).Subject.Should().Be("Nice"); + } + + [Fact] + public async Task MatchFirstAsyncErrorOr_WhenIsError_ShouldExecuteOnFirstErrorAction() + { + // Arrange + ErrorOr errorOrPerson = new List { Error.Validation(), Error.Conflict() }; + Task OnValueAction(Person _) => throw new Exception("Should not be called"); + Task OnFirstErrorAction(Error errors) + { + errors.Should().BeEquivalentTo(errorOrPerson.Errors[0]) + .And.BeEquivalentTo(errorOrPerson.FirstError); + + return Task.FromResult("Nice"); + } + + // Act + var action = async () => await errorOrPerson.MatchFirstAsync( + OnValueAction, + OnFirstErrorAction); + + // Assert + (await action.Should().NotThrowAsync()).Subject.Should().Be("Nice"); + } +} diff --git a/tests/ErrorOr.MatchTests.cs b/tests/ErrorOr.MatchTests.cs index fd3051f..cb0166f 100644 --- a/tests/ErrorOr.MatchTests.cs +++ b/tests/ErrorOr.MatchTests.cs @@ -1,98 +1,98 @@ -using ErrorOr; -using FluentAssertions; - -namespace Tests; - -public class MatchTests -{ - private record Person(string Name); - - [Fact] - public void MatchErrorOr_WhenHasValue_ShouldExecuteOnValueAction() - { - // Arrange - ErrorOr errorOrPerson = new Person("Amichai"); - string OnValueAction(Person person) - { - person.Should().BeEquivalentTo(errorOrPerson.Value); - return "Nice"; - } - - string OnErrorsAction(IReadOnlyList _) => throw new Exception("Should not be called"); - - // Act - Func action = () => errorOrPerson.Match( - OnValueAction, - OnErrorsAction); - - // Assert - action.Should().NotThrow().Subject.Should().Be("Nice"); - } - - [Fact] - public void MatchErrorOr_WhenHasError_ShouldExecuteOnErrorAction() - { - // Arrange - ErrorOr errorOrPerson = new List { Error.Validation(), Error.Conflict() }; - string OnValueAction(Person _) => throw new Exception("Should not be called"); - - string OnErrorsAction(IReadOnlyList errors) - { - errors.Should().BeEquivalentTo(errorOrPerson.Errors); - return "Nice"; - } - - // Act - Func action = () => errorOrPerson.Match( - OnValueAction, - OnErrorsAction); - - // Assert - action.Should().NotThrow().Subject.Should().Be("Nice"); - } - - [Fact] - public void MatchFirstErrorOr_WhenHasValue_ShouldExecuteOnValueAction() - { - // Arrange - ErrorOr errorOrPerson = new Person("Amichai"); - string OnValueAction(Person person) - { - person.Should().BeEquivalentTo(errorOrPerson.Value); - return "Nice"; - } - - string OnFirstErrorAction(Error _) => throw new Exception("Should not be called"); - - // Act - var action = () => errorOrPerson.MatchFirst( - OnValueAction, - OnFirstErrorAction); - - // Assert - action.Should().NotThrow().Subject.Should().Be("Nice"); - } - - [Fact] - public void MatchFirstErrorOr_WhenHasError_ShouldExecuteOnFirstErrorAction() - { - // Arrange - ErrorOr errorOrPerson = new List { Error.Validation(), Error.Conflict() }; - string OnValueAction(Person _) => throw new Exception("Should not be called"); - string OnFirstErrorAction(Error errors) - { - errors.Should().BeEquivalentTo(errorOrPerson.Errors[0]) - .And.BeEquivalentTo(errorOrPerson.FirstError); - - return "Nice"; - } - - // Act - var action = () => errorOrPerson.MatchFirst( - OnValueAction, - OnFirstErrorAction); - - // Assert - action.Should().NotThrow().Subject.Should().Be("Nice"); - } -} +using ErrorOr; +using FluentAssertions; + +namespace Tests; + +public class MatchTests +{ + private record Person(string Name); + + [Fact] + public void MatchErrorOr_WhenIsSuccess_ShouldExecuteOnValueAction() + { + // Arrange + ErrorOr errorOrPerson = new Person("Amichai"); + string OnValueAction(Person person) + { + person.Should().BeEquivalentTo(errorOrPerson.Value); + return "Nice"; + } + + string OnErrorsAction(IReadOnlyList _) => throw new Exception("Should not be called"); + + // Act + Func action = () => errorOrPerson.Match( + OnValueAction, + OnErrorsAction); + + // Assert + action.Should().NotThrow().Subject.Should().Be("Nice"); + } + + [Fact] + public void MatchErrorOr_WhenIsError_ShouldExecuteOnErrorAction() + { + // Arrange + ErrorOr errorOrPerson = new List { Error.Validation(), Error.Conflict() }; + string OnValueAction(Person _) => throw new Exception("Should not be called"); + + string OnErrorsAction(IReadOnlyList errors) + { + errors.Should().BeEquivalentTo(errorOrPerson.Errors); + return "Nice"; + } + + // Act + Func action = () => errorOrPerson.Match( + OnValueAction, + OnErrorsAction); + + // Assert + action.Should().NotThrow().Subject.Should().Be("Nice"); + } + + [Fact] + public void MatchFirstErrorOr_WhenIsSuccess_ShouldExecuteOnValueAction() + { + // Arrange + ErrorOr errorOrPerson = new Person("Amichai"); + string OnValueAction(Person person) + { + person.Should().BeEquivalentTo(errorOrPerson.Value); + return "Nice"; + } + + string OnFirstErrorAction(Error _) => throw new Exception("Should not be called"); + + // Act + var action = () => errorOrPerson.MatchFirst( + OnValueAction, + OnFirstErrorAction); + + // Assert + action.Should().NotThrow().Subject.Should().Be("Nice"); + } + + [Fact] + public void MatchFirstErrorOr_WhenIsError_ShouldExecuteOnFirstErrorAction() + { + // Arrange + ErrorOr errorOrPerson = new List { Error.Validation(), Error.Conflict() }; + string OnValueAction(Person _) => throw new Exception("Should not be called"); + string OnFirstErrorAction(Error errors) + { + errors.Should().BeEquivalentTo(errorOrPerson.Errors[0]) + .And.BeEquivalentTo(errorOrPerson.FirstError); + + return "Nice"; + } + + // Act + var action = () => errorOrPerson.MatchFirst( + OnValueAction, + OnFirstErrorAction); + + // Assert + action.Should().NotThrow().Subject.Should().Be("Nice"); + } +} diff --git a/tests/ErrorOr.SwitchAsyncTests.cs b/tests/ErrorOr.SwitchAsyncTests.cs index 31d3491..9ad2fe0 100644 --- a/tests/ErrorOr.SwitchAsyncTests.cs +++ b/tests/ErrorOr.SwitchAsyncTests.cs @@ -8,7 +8,7 @@ public class SwitchAsyncTests private record Person(string Name); [Fact] - public async Task SwitchAsyncErrorOr_WhenHasValue_ShouldExecuteOnValueAction() + public async Task SwitchAsyncErrorOr_WhenIsSuccess_ShouldExecuteOnValueAction() { // Arrange ErrorOr errorOrPerson = new Person("Amichai"); @@ -25,7 +25,7 @@ public async Task SwitchAsyncErrorOr_WhenHasValue_ShouldExecuteOnValueAction() } [Fact] - public async Task SwitchAsyncErrorOr_WhenHasError_ShouldExecuteOnErrorAction() + public async Task SwitchAsyncErrorOr_WhenIsError_ShouldExecuteOnErrorAction() { // Arrange ErrorOr errorOrPerson = new List { Error.Validation(), Error.Conflict() }; @@ -42,7 +42,7 @@ public async Task SwitchAsyncErrorOr_WhenHasError_ShouldExecuteOnErrorAction() } [Fact] - public async Task SwitchAsyncFirstErrorOr_WhenHasValue_ShouldExecuteOnValueAction() + public async Task SwitchAsyncFirstErrorOr_WhenIsSuccess_ShouldExecuteOnValueAction() { // Arrange ErrorOr errorOrPerson = new Person("Amichai"); @@ -59,7 +59,7 @@ public async Task SwitchAsyncFirstErrorOr_WhenHasValue_ShouldExecuteOnValueActio } [Fact] - public async Task SwitchFirstAsyncErrorOr_WhenHasError_ShouldExecuteOnFirstErrorAction() + public async Task SwitchFirstAsyncErrorOr_WhenIsError_ShouldExecuteOnFirstErrorAction() { // Arrange ErrorOr errorOrPerson = new List { Error.Validation(), Error.Conflict() }; diff --git a/tests/ErrorOr.SwitchTests.cs b/tests/ErrorOr.SwitchTests.cs index 46c05a5..126b1d4 100644 --- a/tests/ErrorOr.SwitchTests.cs +++ b/tests/ErrorOr.SwitchTests.cs @@ -1,79 +1,79 @@ -using ErrorOr; -using FluentAssertions; - -namespace Tests; - -public class SwitchTests -{ - private record Person(string Name); - - [Fact] - public void SwitchErrorOr_WhenHasValue_ShouldExecuteOnValueAction() - { - // Arrange - ErrorOr errorOrPerson = new Person("Amichai"); - void OnValueAction(Person person) => person.Should().BeEquivalentTo(errorOrPerson.Value); - void OnErrorsAction(IReadOnlyList _) => throw new Exception("Should not be called"); - - // Act - var action = () => errorOrPerson.Switch( - OnValueAction, - OnErrorsAction); - - // Assert - action.Should().NotThrow(); - } - - [Fact] - public void SwitchErrorOr_WhenHasError_ShouldExecuteOnErrorAction() - { - // Arrange - ErrorOr errorOrPerson = new List { Error.Validation(), Error.Conflict() }; - void OnValueAction(Person _) => throw new Exception("Should not be called"); - void OnErrorsAction(IReadOnlyList errors) => errors.Should().BeEquivalentTo(errorOrPerson.Errors); - - // Act - var action = () => errorOrPerson.Switch( - OnValueAction, - OnErrorsAction); - - // Assert - action.Should().NotThrow(); - } - - [Fact] - public void SwitchFirstErrorOr_WhenHasValue_ShouldExecuteOnValueAction() - { - // Arrange - ErrorOr errorOrPerson = new Person("Amichai"); - void OnValueAction(Person person) => person.Should().BeEquivalentTo(errorOrPerson.Value); - void OnFirstErrorAction(Error _) => throw new Exception("Should not be called"); - - // Act - var action = () => errorOrPerson.SwitchFirst( - OnValueAction, - OnFirstErrorAction); - - // Assert - action.Should().NotThrow(); - } - - [Fact] - public void SwitchFirstErrorOr_WhenHasError_ShouldExecuteOnFirstErrorAction() - { - // Arrange - ErrorOr errorOrPerson = new List { Error.Validation(), Error.Conflict() }; - void OnValueAction(Person _) => throw new Exception("Should not be called"); - void OnFirstErrorAction(Error errors) - => errors.Should().BeEquivalentTo(errorOrPerson.Errors[0]) - .And.BeEquivalentTo(errorOrPerson.FirstError); - - // Act - var action = () => errorOrPerson.SwitchFirst( - OnValueAction, - OnFirstErrorAction); - - // Assert - action.Should().NotThrow(); - } -} +using ErrorOr; +using FluentAssertions; + +namespace Tests; + +public class SwitchTests +{ + private record Person(string Name); + + [Fact] + public void SwitchErrorOr_WhenIsSuccess_ShouldExecuteOnValueAction() + { + // Arrange + ErrorOr errorOrPerson = new Person("Amichai"); + void OnValueAction(Person person) => person.Should().BeEquivalentTo(errorOrPerson.Value); + void OnErrorsAction(IReadOnlyList _) => throw new Exception("Should not be called"); + + // Act + var action = () => errorOrPerson.Switch( + OnValueAction, + OnErrorsAction); + + // Assert + action.Should().NotThrow(); + } + + [Fact] + public void SwitchErrorOr_WhenIsError_ShouldExecuteOnErrorAction() + { + // Arrange + ErrorOr errorOrPerson = new List { Error.Validation(), Error.Conflict() }; + void OnValueAction(Person _) => throw new Exception("Should not be called"); + void OnErrorsAction(IReadOnlyList errors) => errors.Should().BeEquivalentTo(errorOrPerson.Errors); + + // Act + var action = () => errorOrPerson.Switch( + OnValueAction, + OnErrorsAction); + + // Assert + action.Should().NotThrow(); + } + + [Fact] + public void SwitchFirstErrorOr_WhenIsSuccess_ShouldExecuteOnValueAction() + { + // Arrange + ErrorOr errorOrPerson = new Person("Amichai"); + void OnValueAction(Person person) => person.Should().BeEquivalentTo(errorOrPerson.Value); + void OnFirstErrorAction(Error _) => throw new Exception("Should not be called"); + + // Act + var action = () => errorOrPerson.SwitchFirst( + OnValueAction, + OnFirstErrorAction); + + // Assert + action.Should().NotThrow(); + } + + [Fact] + public void SwitchFirstErrorOr_WhenIsError_ShouldExecuteOnFirstErrorAction() + { + // Arrange + ErrorOr errorOrPerson = new List { Error.Validation(), Error.Conflict() }; + void OnValueAction(Person _) => throw new Exception("Should not be called"); + void OnFirstErrorAction(Error errors) + => errors.Should().BeEquivalentTo(errorOrPerson.Errors[0]) + .And.BeEquivalentTo(errorOrPerson.FirstError); + + // Act + var action = () => errorOrPerson.SwitchFirst( + OnValueAction, + OnFirstErrorAction); + + // Assert + action.Should().NotThrow(); + } +} diff --git a/tests/ErrorOr.ThenAsyncTests.cs b/tests/ErrorOr.ThenAsyncTests.cs index f613f1c..5becc0e 100644 --- a/tests/ErrorOr.ThenAsyncTests.cs +++ b/tests/ErrorOr.ThenAsyncTests.cs @@ -14,15 +14,16 @@ public async Task CallingThenAsync_WhenIsSuccess_ShouldInvokeNextThen() // Act ErrorOr result = await errorOrString .ThenAsync(str => ConvertToIntAsync(str)) + .ThenAsync(num => Task.FromResult(num * 2)) .ThenAsync(num => ConvertToStringAsync(num)); // Assert result.IsError.Should().BeFalse(); - result.Value.Should().BeEquivalentTo(errorOrString.Value); + result.Value.Should().BeEquivalentTo("10"); } [Fact] - public async Task CallingThenAsync_WhenHasError_ShouldReturnErrors() + public async Task CallingThenAsync_WhenIsError_ShouldReturnErrors() { // Arrange ErrorOr errorOrString = Error.NotFound(); @@ -30,6 +31,7 @@ public async Task CallingThenAsync_WhenHasError_ShouldReturnErrors() // Act ErrorOr result = await errorOrString .ThenAsync(str => ConvertToIntAsync(str)) + .ThenAsync(num => Task.FromResult(num * 2)) .ThenAsync(num => ConvertToStringAsync(num)); // Assert diff --git a/tests/ErrorOr.ThenTests.cs b/tests/ErrorOr.ThenTests.cs index ed419e2..0f373a7 100644 --- a/tests/ErrorOr.ThenTests.cs +++ b/tests/ErrorOr.ThenTests.cs @@ -14,15 +14,16 @@ public void CallingThen_WhenIsSuccess_ShouldInvokeGivenFunc() // Act ErrorOr result = errorOrString .Then(str => ConvertToInt(str)) + .Then(num => num * 2) .Then(num => ConvertToString(num)); // Assert result.IsError.Should().BeFalse(); - result.Value.Should().BeEquivalentTo(errorOrString.Value); + result.Value.Should().BeEquivalentTo("10"); } [Fact] - public void CallingThen_WhenHasError_ShouldReturnErrors() + public void CallingThen_WhenIsError_ShouldReturnErrors() { // Arrange ErrorOr errorOrString = Error.NotFound(); @@ -30,6 +31,7 @@ public void CallingThen_WhenHasError_ShouldReturnErrors() // Act ErrorOr result = errorOrString .Then(str => ConvertToInt(str)) + .Then(num => num * 2) .Then(num => ConvertToString(num)); // Assert @@ -39,6 +41,24 @@ public void CallingThen_WhenHasError_ShouldReturnErrors() [Fact] public async Task CallingThenAfterThenAsync_WhenIsSuccess_ShouldInvokeGivenFunc() + { + // Arrange + ErrorOr errorOrString = "5"; + + // Act + ErrorOr result = await errorOrString + .ThenAsync(str => ConvertToIntAsync(str)) + .Then(num => num * 2) + .ThenAsync(num => ConvertToStringAsync(num)) + .Then(str => ConvertToInt(str)); + + // Assert + result.IsError.Should().BeFalse(); + result.Value.Should().Be(10); + } + + [Fact] + public async Task CallingThenAfterThenAsync_WhenIsError_ShouldReturnErrors() { // Arrange ErrorOr errorOrString = Error.NotFound(); @@ -58,4 +78,6 @@ public async Task CallingThenAfterThenAsync_WhenIsSuccess_ShouldInvokeGivenFunc( private static ErrorOr ConvertToInt(string str) => int.Parse(str); private static Task> ConvertToIntAsync(string str) => Task.FromResult(ErrorOrFactory.From(int.Parse(str))); + + private static Task> ConvertToStringAsync(int num) => Task.FromResult(ErrorOrFactory.From(num.ToString())); }