Redux-Saga와 함께 fp-ts TaskEither 모나드 사용
10195 단어 sagatypescriptfunctionalredux
TaskEither<L, R>
monad은 성공 시 R
유형의 값을 반환하고 실패 시 L
유형의 값을 반환하는 비동기 계산을 나타내는 강력한 데이터 구조입니다. 예외(😖)를 처리하는 대신 더 "기능적"이고 투명한 방식으로 오류를 처리할 수 있습니다.나는 최근에 Redux-Saga 내부에서 그것을 사용하고 있음을 발견했고
TaskEither
효과를 사용하여 call
를 반환하는 함수를 실행했습니다. 이제 TaskEither
는 Promise
를 반환하는 함수일 뿐이므로 실제로 그렇게 하는 것은 매우 쉽습니다. 언뜻보기에 우리는 다음과 같이 할 수 있습니다.// The service returning a `TaskEither`.
export function service(param: string): TE.TaskEither<Error, string> {
return TE.right(`Hello World, ${param}`)
}
// The saga executing the service.
export function* saga() {
// Either<Error, string>
const result = yield* call(service('param'))
}
The
yield*
operator here is used for typed-redux-saga, to obtain a better typing inside a Saga.
이런 식으로
result
는 실제로 Either<Error, string>
유형이지만 call
와 같은 인수를 전달하는 대신 함수를 직접 호출하여 call(service, 'param')
를 잘못 사용하고 있습니다. 이것은 Saga에 대한 단위 테스트를 작성할 때 문제를 일으킬 것입니다. 그렇다면 올바른 방식으로 서비스를 전달하면 어떻게 될까요? 그러면 다음과 같이 작성해야 합니다.// TaskEither<Error, string>
const unexecutedResult = yield* call(service, 'param')
// Either<Error, string>
const result = yield* call(unexecutedResult)
이 경우
unexecutedResult
는 TaskEither<Error, string>
유형이며 구체적인 결과를 얻으려면 실제로 실행해야 합니다. 이것은 작동하지만 단일 "작업"에 대해 두 가지call
효과를 테스트해야 합니다. 😾 정말 싫어요. 하지만 약간의 TypeScript 마법을 사용하여 단일 호출로 TaskEither
를 만들고 실행하는 유틸리티 함수를 작성하여 이를 개선할 수 있습니다./**
* Utility to evaluate a function returning a `TaskEither`.
*/
function* callTaskEither<
L,
R,
Fn extends (...genericArgs: Array<any>) => TE.TaskEither<L, R>,
>(fn: Fn, ...args: Parameters<Fn>): SagaGenerator<E.Either<L, R>> {
const task: TE.TaskEither<L, R> = yield* call(fn, ...args)
return yield* call(task)
}
/**
* Evaluate a one-argument function returning a TaskEither.
*/
export function callTaskEither1<L, R, P1>(
fn: (p1: P1) => TE.TaskEither<L, R>,
p1: P1,
): SagaGenerator<E.Either<L, R>> {
return callTaskEither(fn, p1)
}
/**
* Helper type for `callTaskEither1`.
*/
export type TCallTaskEither1<L, R, P1> = (
fn: (p1: P1) => TE.TaskEither<L, R>,
p1: P1,
) => SagaGenerator<E.Either<L, R>>
함수
callTaskEither
는 앞에서 설명한 두 가지call
를 수행하는 생성기일 뿐입니다. TypeScript는 스프레드 연산자를 사용하여 함수의 매개변수를 유추하는 데 문제가 있으므로 필요한 각 매개변수 수에 대해 수동으로 도우미 함수와 유형을 만들어야 합니다. 최고는 아니지만 일회성 작업입니다! 이 힘든 작업을 통해 다음과 같이 단일call
효과를 사용하여 작업 유형 검사를 할 수 있습니다.// Either<Error, string>
const result = yield* call<TCallTaskEither1<Error, string, string>>(
callTaskEither1,
service,
'param',
)
여전히 약간 장황하지만 실제로 모든 곳에서 두 가지
call
효과를 사용하는 것보다 선호합니다!봐요 🤠
Reference
이 문제에 관하여(Redux-Saga와 함께 fp-ts TaskEither 모나드 사용), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/dgopsq/using-the-fp-ts-taskeither-monad-with-redux-saga-37lp텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)