[한입] 프로미스와 제네릭

TK·2023년 12월 17일
0

[강의] 한입 시리즈

목록 보기
45/59

타입스크립트의 제네릭을 활용하여 비동기 처리를 돕는 프로미스 객체의 타입을 정의해보자.

프로미스 이론 공부하고 오기

프로미스

(Promise)

✏️성공 (resolve)

  • 일반적인 비동기 코드
const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(20); // 비동기 작업 성공시, 결과값
  }, 3000);
});

promise.then((response) => {
  console.log(response); // 20
});

  • 여기서 다음과 같이 결과값에 곱셈연산 시 오류가 나타남 (unknown 타입)
    결과값이 20으로 number타입이라 이것이 자동으로 추론되길 기대하지만 실제 이 기능은 없음
const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(20);
  }, 3000);
});

promise.then((response) => {
  console.log(response * 10); // ❌오류
});


  • promise 생성자를 호출할 때 타입변수를 할당 → 비동기 처리 결과값의 타입도 직접 명시 가능
const promise = new Promise<number>((resolve, reject) => { // 👈타입변수 할당
  setTimeout(() => {
    resolve(20);
  }, 3000);
});

promise.then((response) => {
  console.log(response * 10); // 200
});

✏️실패 (reject)

  • reject의 타입은 any타입으로 설정되어 있다.

  • 실패한 경우의 타입은 별도로 정해줄 수 없지만 에러의 형태를 타입좁히기를 통해 원하는 값만 받아온다.
const promise = new Promise<number>((resolve, reject) => {
  setTimeout(() => {
    // resolve(20);
    reject("~때문에 실패");
  }, 3000);
});

promise.then((response) => {
  console.log(response * 10);
});

promise.catch((err) => {
  if (typeof err === "string") {
    console.log(err);
  }
});

✏️프로미스 반환 함수타입 정의

  • 서버로부터 하나의 게시글의 데이터를 불러오는 함수를 작성할 때
interface Post {
  id: number;
  title: string;
  content: string;
}

function fetchPost() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve({
        id: 1,
        title: "게시글 제목",
        content: "게시글 컨텐츠",
      });
    }, 3000);
  });
}

const postResquest = fetchPost();

postResquest.then((post) => {
  post.id; // ❌오류
});

  • postunknown타입이므로 오류가 발생한다.

  • 해결방법1: Post타입 변수 할당
interface Post {
  id: number;
  title: string;
  content: string;
}

function fetchPost() {
  return new Promise<Post>((resolve, reject) => { // 👈
    setTimeout(() => {
      resolve({
        id: 1,
        title: "게시글 제목",
        content: "게시글 컨텐츠",
      });
    }, 3000);
  });
}

const postResquest = fetchPost();
postResquest.then((post) => {
  post.id; // 오류 사라짐
});

Promise는 class이기 때문에 타입으로도 활용되고 있음


  • 해결방법2: fetchPost함수의 반환값 타입으로 Promise<Post> 설정
interface Post {
  id: number;
  title: string;
  content: string;
}

function fetchPost(): Promise<Post> { // 👈
  return new Promise((resolve, reject) => { 
    setTimeout(() => {
      resolve({
        id: 1,
        title: "게시글 제목",
        content: "게시글 컨텐츠",
      });
    }, 3000);
  });
}

const postResquest = fetchPost();
postResquest.then((post) => {
  post.id; // 오류 사라짐
});

해결방법2를 선호하는 이유 ※

  1. 협업의 관점에서 함수의 선언부분만 보고도 "fetchPost함수는 Promise를 반환하는구나!" 라고 바로 확인가능 → 가독성↑
  2. 함수 내부가 길어지면 리턴문 타입을 찾기위해 계속 찾아봐야 함
profile
쉬운게 좋은 FE개발자😺

0개의 댓글