TypeScript Result
npm install ts-res
Tiny library to improve error handling in TS using Rust-inspired types.
- Installation
- Result Type
- Helper Methods
- Examples
- Using npm - npm install ts-res
- Using yarn - yarn add ts-res
- Using pnpm - pnpm add ts-res
Result type is convenient to use as a return type of a method that may fail.
In Result:
- T specifies success result type, which can be any type
- E specifies error type, which is constrained by Error | string | void | undefined.
Err() and Ok() are used as a return type enforcers.
``ts
function mayFail(isFailed: boolean): Result
if (isFailed) {
return Err(new Error("Function failed"));
}
return Ok(123);
}
`
As a result we get an object which will either be {ok: true, data: T} or {ok: false, error: E}
_Note:_ Ok() and Err() can be used with no values if T/E were specified as void or undefined
`ts
function getEmptyResult(isFailed: boolean): Result
if (isFailed) {
return Err();
}
return Ok();
}
`
Result can be handled manually:
`ts
const result = mayFail(true);
if (!result.ok) {
throw result.error;
}
console.log(result.data);
`
However it's much easier to use helper methods to quickly handle the result:
- throw(message?: string) - throws an error (with an optional custom error message) or returns an unwrapped resultor(value: T)
- - returns an unwrapped result or a back-up valueelse(callback: (error: E) => T)
- - returns an unwrapped result or executes callback that returns back-up value which can be based on provided errorand(callback: (result: T) => Result
- - handles a result in a callback while ignoring an error, returns the result allowing for chaining
`ts
// -- throw()
mayFail(true).throw(); // returns 123
mayFail(false).throw(); // throws an Error with default message
mayFail(false).throw("My Message"); // throws an Error with "My Message"
// -- or()
mayFail(true).or(100); // returns 123
mayFail(false).or(100); // returns 100
// -- else()
mayFail(true).else((error) => 200); // returns 123
mayFail(false).else((error) => 200); // returns 200 (error can be used for some extra logic)
// -- and()
mayFail(true).and((result) => {
console.log(result);
}); // logs 123
mayFail(false).and((result) => {
console.log(result);
}); // doesn't do anything
`
More elaborate examples:
- Use throw() to unwrap the value after parsing a number
`typescript
function toNumber(str: string): Result
const result = Number(str);
if (isNaN(result)) {
return Err("Couldn't parse a string");
}
return Ok(result);
}
const myNumber: number = toNumber("Hello").throw(); // Throws an Error
const myNumber: number = toNumber("123").throw(); // Returns 123
`
- Use or() to provide a back-up value while obtaining status code
`ts
function getStatusCode(statusCode: number): Result
if (statusCode > 200 && statusCode < 300) {
return Ok(statusCode);
}
return Err("Invalid status code");
}
function obtainStatus(): number {
return getStatusCode(response.statusCode).or(404); // Returns statusCode between 201 and 299 or 404`
}
- Use else() and CustomError to provide a back-up value based on error type
`ts
enum ErrorType {
A,
B,
C,
}
class CustomError extends Error {
private errorType: ErrorType;
constructor(type: ErrorType) {
super();
this.errorType = type;
}
get type(): ErrorType {
return this.errorType;
}
}
function myFunction(): Result
//...
}
myFunction().else((error) => {
switch (error.type) {
case ErrorType.A:
return "a";
case ErrorType.B:
return "b";
case ErrorType.C:
return "c";
default:
break;
}
});
`
- Use and() to handle a result of writing data to localStorage and ignore the error`ts
function readLocalStorage(key: string): Result
const data = localStorage.getItem(key);
if (!data) {
return Err();
}
return Ok(data);
}
readLocalStorage.and((data) => {
const parsedData = JSON.parse(data);
console.log(parsedData);
})
`
- Use and() for handling http response data and chaining it with another method`ts
type User = {
name: string;
age: number;
};
async function fetchUserData(): Promise
const response = await fetch("https://api.example.com/user");
if (!response.ok) {
return Err(new Error("Failed to fetch user data"));
}
const data = await response.json();
return Ok(data);
}
const result = await fetchUserData();
result
.and((user) => {
console.log(user);
})
.else((error) => {
console.error(error);
});
``