Wrapper around promise for functional programming
npm install @vladbasin/ts-result
This library brings elements of functional programming to TypeScript/JavaScript. See Use cases section for details.
npm install @vladbasin/ts-resultyarn add @vladbasin/ts-result``typescript`
showLoader();
try {
const wallet = await getWalletAsync();
if (wallet.money < 10) {
alert("Not enough money");
return;
}
const item = await getItemAsync();
const response = await purchaseAsync(item);
if (!response.success) {
alert(response.error);
return;
}
log("Purchase success");
}
catch (error) {
alert(error);
}
finally {
hideLoader();
}
However, with this library instead you can write nice readable chains of methods:
`typescript
import { Result } from "@vladbasin/ts-result";
showLoader();
Result
.FromPromise(getWalletAsync())
.ensure(wallet => wallet.money > 10, "Not enough money")
.onSuccess(() => getItemAsync(itemId))
.onSuccess(item => purchaseAsync(item))
.ensure(response => response.success, response.error)
.onFailure(error => alert(error))
.onSuccess(() => log("Purchase success"))
.onBoth(result => hideLoader())
.run();
`
Without this library (poor readability, code repeats)
`typescript`
const usernameValidation = validateUsername(username);
if (!usernameValidation.success) {
alert(usernameValidation.error)
return;
}
const passwordValidation = validatePassword(password);
if (!passwordValidation.success) {
alert(passwordValidation.error)
return;
}
const passwordRepeatValidation = validatePasswordRepeat(passwordRepeat, password);
if (!passwordRepeatValidation.success) {
alert(passwordRepeatValidation.error)
return;
}
With this library (readable code, reusable logic)
`typescript
import { Result } from "@vladbasin/ts-result";
Result
.Start()
.onSuccess(() => validateUsername(username))
.onSuccess(() => validatePassword(password))
.onSuccess(() => validatePasswordRepeat(passwordRepeat, password))
.onFailure(error => alert(error))
.run();
`
To achieve this, you can use methods like withProcessedError to mark errors as processed. This ensures that subsequent error handling logic does not override the already processed error.
Below code processes failure from getDataAsync() call and ensures that error is processed by next service only if it was not processed before:
`typescript
import { Result, ProcessedError } from "@vladbasin/ts-result";
Result
.FromPromise(getDataAsync())
.withProcessedFail(response => accountService.processErrors(response))
.withProcessedFail(response => walletService.processErrors(response)) // will not be called if accountService.processErrors() already processed response and found error
.onFailure((error) => {
// do something with errors
})
.onSuccess((data) => {
// execute logic if getDataAsync call was successful
})
`
as a return type and continue using Promise while benefiting from Result functionality, you can always:- Convert
Result to Promise: result.asPromise()
- Convert Promise to Result: Result.FromPromise(YOUR_PROMISE)$3
The Combiner class provides several methods to combine multiple Result instances into one. This is useful when you need to execute multiple asynchronous operations in parallel and handle their results collectively.#### Combining Two Results
`typescript
import { Result, Combiner } from "@vladbasin/ts-result";const result1 = Result.FromPromise(fetchData1());
const result2 = Result.FromPromise(fetchData2());
Combiner.Combine2(result1, result2)
.onSuccess(([data1, data2]) => {
console.log("Data1:", data1);
console.log("Data2:", data2);
})
.onFailure(error => {
console.error("Error:", error);
})
.run();
`#### Combining Multiple Results
`typescript
import { Result, Combiner } from "@vladbasin/ts-result";const results = [
Result.FromPromise(fetchData1()),
Result.FromPromise(fetchData2()),
Result.FromPromise(fetchData3())
];
Combiner.CombineMany(results)
.onSuccess(dataArray => {
dataArray.forEach((data, index) => {
console.log(
Data${index + 1}:, data);
});
})
.onFailure(error => {
console.error("Error:", error);
})
.run();
`$3
You can execute multiple actions with given parallelism level (concurrency)
`typescript
import { Result } from "@vladbasin/ts-result";const factories = [
() => Result.FromPromise(fetchData1()),
() => Result.FromPromise(fetchData2()),
() => Result.FromPromise(fetchData3())
];
Result.CombineFactories(factories, { concurrency: 2 })
.onSuccess(dataArray => {
dataArray.forEach((data, index) => {
console.log(
Data${index + 1}:, data);
});
})
.onFailure(error => {
console.error("Error:", error);
})
.run();
``