Change the Either type signature
This commit is contained in:
parent
8abf4923a4
commit
5f84339d77
@ -7,6 +7,7 @@ tags:
|
|||||||
- Development
|
- Development
|
||||||
- Guide
|
- Guide
|
||||||
---
|
---
|
||||||
|
|
||||||
We have started a new small internal project for automating a few workflows around counting worked hours and time offs.
|
We have started a new small internal project for automating a few workflows around counting worked hours and time offs.
|
||||||
|
|
||||||
## Application architecture
|
## Application architecture
|
||||||
@ -43,11 +44,11 @@ export class InternalError extends Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Then, we can create multiple app-specific errors by extending from these two.
|
Then, we can create multiple app-specific errors by extending from these two.
|
||||||
|
|
||||||
> We need to set `Object.setPrototypeOf(...)` as TypeScript [introduced a breaking change](https://github.com/Microsoft/TypeScript-wiki/blob/main/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work) that may cause the inheritance to now work properly.
|
> We need to set `Object.setPrototypeOf(...)` as TypeScript [introduced a breaking change](https://github.com/Microsoft/TypeScript-wiki/blob/main/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work) that may cause the inheritance to now work properly.
|
||||||
|
|
||||||
|
|
||||||
## Handling errors
|
## Handling errors
|
||||||
|
|
||||||
I wanted to have a similar style of handling the error as the [Ramda's `tryCatch`](https://ramdajs.com/docs/#tryCatch) function. I couldn't just use Ramda's `tryCatch` as it doesn't support asynchronous functions. I've found inspiration in the [`fp-ts` `TaskEither` type](https://gcanti.github.io/fp-ts/modules/TaskEither.ts.html).
|
I wanted to have a similar style of handling the error as the [Ramda's `tryCatch`](https://ramdajs.com/docs/#tryCatch) function. I couldn't just use Ramda's `tryCatch` as it doesn't support asynchronous functions. I've found inspiration in the [`fp-ts` `TaskEither` type](https://gcanti.github.io/fp-ts/modules/TaskEither.ts.html).
|
||||||
@ -59,7 +60,7 @@ I've come up with the following solution:
|
|||||||
* Tuple of error and a result of an asynchronous task that might throw an error
|
* Tuple of error and a result of an asynchronous task that might throw an error
|
||||||
*/
|
*/
|
||||||
export type Either<ResultType, ErrorType extends Error> = Promise<
|
export type Either<ResultType, ErrorType extends Error> = Promise<
|
||||||
[error: ErrorType | null, result?: ResultType]
|
[error: null, result: ResultType] | [error: ErrorType, result: undefined]
|
||||||
>
|
>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -102,7 +103,9 @@ As most of the errors will be possibly handled by the same `errorHandle` we can
|
|||||||
* It will throw an error if any unexpected error is thrown
|
* It will throw an error if any unexpected error is thrown
|
||||||
* When used with `wrapWithErrorHandler` it is able to catch most of the expected errors
|
* When used with `wrapWithErrorHandler` it is able to catch most of the expected errors
|
||||||
*/
|
*/
|
||||||
export function genericErrorHandler<ErrorType extends Error>(exception: ErrorType | unknown) {
|
export function genericErrorHandler<ErrorType extends Error>(
|
||||||
|
exception: ErrorType | unknown
|
||||||
|
) {
|
||||||
if (exception instanceof PublishableError) {
|
if (exception instanceof PublishableError) {
|
||||||
// These errors are usually handled no need to log them
|
// These errors are usually handled no need to log them
|
||||||
return exception
|
return exception
|
||||||
@ -129,9 +132,10 @@ To spare some characters of redundant code I've applied a partial application pr
|
|||||||
/**
|
/**
|
||||||
* Helper function with applied `genericErrorHandler` to `wrapWithErrorHandler`
|
* Helper function with applied `genericErrorHandler` to `wrapWithErrorHandler`
|
||||||
*/
|
*/
|
||||||
export function wrapWithGenericErrorHandlerFunction<FunctionArgs extends Array<any>, ResultType>(
|
export function wrapWithGenericErrorHandlerFunction<
|
||||||
fn: (...args: FunctionArgs) => Promise<ResultType>
|
FunctionArgs extends Array<any>,
|
||||||
) {
|
ResultType
|
||||||
|
>(fn: (...args: FunctionArgs) => Promise<ResultType>) {
|
||||||
return wrapWithErrorHandler(genericErrorHandler, fn)
|
return wrapWithErrorHandler(genericErrorHandler, fn)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -141,11 +145,13 @@ export function wrapWithGenericErrorHandlerFunction<FunctionArgs extends Array<a
|
|||||||
To sum it up, I'd like to present you the way how this API is used:
|
To sum it up, I'd like to present you the way how this API is used:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
const [error, memberId] = await wrapWithGenericErrorHandlerFunction(getUserId)(user.token)
|
const [error, memberId] = await wrapWithGenericErrorHandlerFunction(getUserId)(
|
||||||
if (error) {
|
user.token
|
||||||
await respond(error.message)
|
)
|
||||||
return
|
if (error) {
|
||||||
}
|
await respond(error.message)
|
||||||
|
return
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
This API allows me to keep the separation of concerns between the tasks and error handling into two separate functions. It also allows us to use the `wrapWithErrorHandler` with different `errorHandler` when we need to take special care. Also, I am still able to throw errors from the `errorHandler` that might be caught by a different `errorHandler` from an upper scope.
|
This API allows me to keep the separation of concerns between the tasks and error handling into two separate functions. It also allows us to use the `wrapWithErrorHandler` with different `errorHandler` when we need to take special care. Also, I am still able to throw errors from the `errorHandler` that might be caught by a different `errorHandler` from an upper scope.
|
||||||
|
Loading…
Reference in New Issue
Block a user