TypeScript의 Thenable<R>
설명
Thenable<R>
은 TypeScript에서 “Thenable” 패턴을 구현하는 객체 타입을 나타냅니다. Promise<R>
와 유사하지만, 엄격한 Promise 객체가 아닌, then
메서드를 가진 객체를 의미합니다.
1. Thenable<R>
의 기본 개념
Thenable<R>
은 PromiseLike<R>
와 거의 동일한 개념입니다. 즉, then
메서드를 제공하지만, 꼭 Promise
인스턴스일 필요는 없습니다.
<pre class="wp-block-syntaxhighlighter-code">interface Thenable<R> {
then<TResult1 = R, TResult2 = never>(
onfulfilled?: ((value: R) => TResult1 | PromiseLike<TResult1>) | undefined | null,
onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null
): Thenable<TResult1 | TResult2>;
}
</pre>
이 인터페이스의 핵심은 then
메서드를 포함하는 것입니다.
즉, 해당 객체는 Promise처럼 동작하지만 Promise
클래스의 인스턴스가 아닐 수도 있습니다.
2. Thenable<R>
의 특징
Promise<R>
와는 달리, 자체적으로 구현된 thenable 객체를 만들 수 있음.- JavaScript의 Promise 체인과 호환될 수 있도록 동작함.
async/await
를 사용할 때도Promise
처럼 동작할 수 있음.
3. Thenable<R>
예제
Thenable<R>
을 직접 구현하는 예제:
<pre class="wp-block-syntaxhighlighter-code">class MyThenable<T> implements Thenable<T> {
constructor(private value: T) {}
then<TResult1 = T, TResult2 = never>(
onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null,
onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null
): Thenable<TResult1 | TResult2> {
try {
const result = onfulfilled ? onfulfilled(this.value) : (this.value as unknown as TResult1);
return new MyThenable(result as TResult1);
} catch (error) {
if (onrejected) {
return new MyThenable(onrejected(error) as TResult2);
}
throw error;
}
}
}
// 사용 예제
const thenable = new MyThenable(42);
thenable.then((value) => {
console.log("Value:", value);
return value * 2;
}).then((newValue) => {
console.log("New Value:", newValue);
});
</pre>
출력 결과
Value: 42
New Value: 84
위 코드에서는 MyThenable<T>
클래스가 Thenable<T>
인터페이스를 구현하여, Promise
처럼 동작하지만, Promise
의 인스턴스는 아닌 객체를 생성합니다.
4. Thenable<R>
과 Promise<R>
차이점
특징 | Thenable | Promise |
---|---|---|
then 메서드 포함 여부 |
✅ | ✅ |
catch 및 finally 지원 여부 |
❌ | ✅ |
await 에서 정상적으로 동작 |
✅ | ✅ |
Promise 의 인스턴스 여부 |
❌ | ✅ |
직접 구현 가능 여부 | ✅ | ❌ (일반적으로 new Promise() 사용) |
5. 실전에서 사용 예시
(1) Thenable
객체가 Promise
처럼 동작
Thenable<R>
객체는 Promise.resolve()
를 사용할 때, 자동으로 Promise
로 변환됩니다.
const thenable = {
then(resolve: (value: number) => void) {
resolve(100);
}
};
Promise.resolve(thenable).then((value) => {
console.log(value); // 100
});
위 코드에서 thenable
객체는 Promise.resolve()
에 전달되었고, 내부적으로 then()
을 실행하여 값이 전달되었습니다.
(2) async/await
과 함께 사용
Thenable
객체는 async/await
문법에서도 정상적으로 동작합니다.
const thenable = {
then(resolve: (value: string) => void) {
setTimeout(() => resolve("Hello, Thenable!"), 1000);
}
};
async function run() {
const result = await thenable;
console.log(result); // "Hello, Thenable!" (1초 후 출력)
}
run();
위 코드에서 thenable
객체는 await
키워드로 정상적으로 처리되었습니다. 즉, Promise
처럼 작동할 수 있습니다.
6. 결론
Thenable<R>
은Promise<R>
와 비슷하지만, Promise의 인스턴스가 아닌then
메서드만을 가진 객체를 의미합니다.- TypeScript의
PromiseLike<R>
와 거의 동일한 개념이며,Promise.resolve()
나async/await
에서 자동 변환될 수 있습니다. - 직접 구현할 수도 있으며,
Promise
와 유사한 동작을 하도록 만들 수 있습니다.
Thenable
을 활용하면 커스텀 비동기 처리 로직을 유연하게 만들거나, 기존 비동기 API와의 호환성을 유지하는 데 도움이 됩니다. 🚀