typescript에서 예외를 처리하는 기능적 방법
const even = (a: number) => {
if (a % 2 === 0) {
return a
}
throw new Error(`value: ${a} is even`);
}
값이 짝수인지 알 수 있듯이 숫자를 반환하지 않으면 오류가 발생합니다. 이것을 처리하는 일반적인 방법은 try-catch 안에 래핑하고 오류를 처리하는 것입니다. 그러나 여러 기능이 있는 경우 이는 지루하고 오류가 발생하기 쉽습니다.
f 세계에서는 모든 곳에 오류를 던지는 대신 데이터로 변환합니다. 이것은 typescript에서 다음과 같이 보일 것입니다:
type Try<A> = Success<A> | Failure
Where 성공 is a container that wraps some value of type A and Failure is the alternative one that contains the error.
Let’s try to implement this structure! We will use a mix of OOP and FP, to create nicely chainable data structures. First, we will create an abstract class that will contain the types of our methods that our data structure will define
abstract class Try<A> {
abstract map<B>(this: Try<A>, fn: (a: A) => B): Try<B>
abstract chain<B>(this: Try<A>, fn: (a: A) => Try<B>): Try<B>;
}
We defined two abstract methods: map and chain. The map
function acts the same as it does in Array with one element. It takes the value and applies a function over it then "magically" it will be packed back into the array.
Basically:
[1].map(x => `${x}`).
In types:
Array<Int> => (fn: (a: Int) => string) => Array<string>
The chain
method is a bit more complicated. While the map just takes out the value, applies a function over it, and packs it back, with a chain it is your responsibility to pack it.
Our analog in an array of one element would be the following:
[1].flatMap(x => [`${x * 2}`]).
In types:
Array<Int> => (fn: (a: Int) => Array<string>) => Array<string>
You may ask why is this chain
method useful anyway? As its name suggests we will use it to chain together multiple functions.
Before we continue implementing Success we need to introduce the concept of laziness.
The function arguments in javascript are called by value. What does this mean?
For example:
function a(arg) {
console.log(“hi”)
}
function b(a, b) {
throws new Error(“Hello From the other side” + a + b)
}
a(b(1, 2))
What will happen here? Even if the argument of the function a
was not used we still executed the function b
and an error was thrown. How can we solve this? What if we would want to call it inside of a
?
Here our some helpers that solves our issue:
// pass as thunk
type $<A> = () => A
function $<A>(a: A): $<A>{
return () => a
}
// make function lazy
function $fn<A extends (...args: any) => any>(a: A): ((...p: Parameters<A>) => $<ReturnType<A>>) {
return (...p: [Parameters<A>]) => () => {
return a(...p)
}
}
class Success<A> extends Try<A> {
value: A
constructor(a: A) {
super()
this.value = a;
}
static of<A>(value: A): Try<A> { return new Success(value); }
map<B>(fn: (a: A) => B): Try<B> {
const val = this.value;
const x = $fn(fn)(val);
return mkTry<B>(x)
}
chain<B>(fn: (a: A) => Try<B>): Try<B> {
return fn(this.value);
}
}
그리고 실패:
class Failure<A> extends Try<A> {
value: Error;
constructor(e: Error) {
super();
this.value = e;
}
static of<A>(value: Error): Try<A> { return new Failure(value); }
map<B>(fn: (a: A) => B): Try<B> {
return Failure.of(this.value);
}
chain<B>(fn: (a: A) => Try<B>): Try<B> {
return Failure.of(this.value)
}
}
우리의 삶을 더 쉽게 만들기 위해 도우미 함수를 만들 수 있습니다.
function mkTry<A>(value: $<A>): Try<A> {
try {
const a = value();
return Success.of(a)
} catch (error) {
return Failure.of(error as Error)
}
}
이제 이를 통해 코드를 안전하게 연결하고 실행할 수 있는 메커니즘을 갖게 되었습니다.
예시:
// // define a simple function that throws an error
const x = (a: number) => {
if (a % 2 === 0) {
return a
}
throw new Error(`value: ${a} is even`);
}
const div4 = (a: number) => {
if (a % 4 === 0) {
return a
}
throw new Error(`value: ${a} is not dividible by 4`);
}
// make it lazy
const lazyX = $fn(x)
const lazyDiv = $fn(div4)
// // wrap inside try, map chain
const a1 = Try.lift(12)
.chain(a => mkTry(lazyX(a)))
.map(b => (b * 2) - 4)
.chain(a => mkTry(lazyDiv(a)));
console.log(a1);
이 예제에서 우리는 오류를 던질 수 있는 몇 가지 함수를 정의한 다음, 그것들을 게으르게 만들고 Try using mkTry 데이터 생성자를 사용하여 래핑했습니다.
조금이나마 도움이 되었길 바랍니다 :) 질문이 있으시면 댓글을 남겨주세요.
전체 구현은 다음을 참조하십시오. https://gist.github.com/lupuszr/f73baa7ef559f77e6e847ba75ed97182
Reference
이 문제에 관하여(typescript에서 예외를 처리하는 기능적 방법), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/lupuszr/functional-way-for-handling-exceptions-in-typescript-coc텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)