티스토리 뷰

오버로딩

  • 타입을 하나로만 정의하는 것이 베스트긴하지만 다 정의하지 못할 때 사용한다.(제네릭으로 깔끔하게 못만들겠다 싶을때 쓰면 좋을듯)
  • 오버로딩을 했으면 실제 구현부에서는 any를 사용해도 된다. (아래 추가설명)
  • 함수도 앞에 declare키워드를 붙이고 오버로딩이 가능하다. (declare키워드가 붙은 함수는 TS를 속여 body부분을 작성해주지 않고 선언부만 적어도 된다.) -> 여기서 실제 사용할 때의 구현부 타입은 any로 지정해줘도 된다(오버로딩된 타입들이 제대로 작성되어 있다면).  
// declare를 함수 앞에 붙이면 선언만하고 구현부(body부분)는 쓰지 않아도 TS가 인식하기로는 구현부는 다른 곳에 있구나
//라고 속일 수 있다.
declare function add(x: number, y: number): number;
declare function add(x: number, y: number, z?: number): number;
declare function add(x: string, y: string): string;
add(1, 2);
add(2, 3, 4);
add("1", "2");
  • 인터페이스, 클래스 내부에서 전부 오버로딩가능
interface Add {
    (x: number, y: number): number;
    (x: string, y: string): string;
  }
  const add: Add = (x: any, y: any) => x + y;
  add(1, 2);
  add("1", "2");
  // add("1", 2);

  class A {
    add(x: number, y: number): number;
    add(x: string, y: string): string;
    add(x: any, y: any) {
      return x + y;
    }
  }
  const c = new A().add(1, 2); // c는 number

에러 핸들링

//타입스크립트 에러 처리법(부제: TS는 건망증이 심하다)
//타입을 모두 정의하려면 머리아픔-> 지금 내가 쓰고 있는 코드가 돌아가게끔 만들면 된다.
//err는 무조건 unknown인데 즉 as로 타입명시를 사용시 해줘야 한다.
interface Axios {
  get(): void;
}
//기존 JS Error 객체에는 아래의 속성밖에 없음
/*
 name: string;
 message: string;
 stack?: string;
*/
interface CustomError extends Error {
  //response값이 있을수도 없을 수도 있기 때문에 "?""
  response?: {
    data: any;
  };
}
declare const axios: Axios;
(async () => {
  try {
    await axios.get();
  } catch (err: unknown) {
    console.error((err as CustomError).response?.data);
  }
})();

-> 위의 코드에서 분명 err가 CustomError에서 온 것이라는 것이라고 unknown을 제대로 명시했는데 바로 다음줄에서 

err.response?.data를 사용하려면 에러가 난다.

  • (error as CustomError)는 일회성으로 Type Assertion(타입 단언)를 한 것이다. 저장된 것이 아니기 때문에 다음 코드에서 재사용하려면 변수에 담아줘야 한다. 
😅TS는 건망증이 심해서 다시 err를 쓸 때, (err as CustomError)로 명시해줘야 한다.
해결방법: 데이터를 변수에 담아서 타입을 저장해줘야 한다.

이렇게되면 as 범벅이 될 것이다. 이럴 땐, 가장 상단에 변수를 만들어 담아서 쓰면 된다.

(async () => {
  try {
    await axios.get();
  } catch (err: unknown) {
    const myError = err as CustomError; //변수에 담음
    console.error(myError.response?.data);
    console.log(myError); //CustomError로 타입이 잘 뜨는 것을 확인할 수 있다.
  }
})();
 any만큼 안 좋은 것이 as(Type Assertion)이기 때문에 많이 안쓰는 것이 좋다. 하지만 어쩔 수 없이 unknown타입이 있을 때는 as를 써서 타입을 명시해줘야 한다. *error 는 타입이 unknown으로 고정되어 있기 때문에 이럴 땐 as로 타입을 고정해줘야 하겠죠? 

인터페이스 vs 클래스 

-> 인터페이스는 js코드로 변환했을 때 사라진다. 즉 instanceof 키워드를 사용하지 못한다. (타입 별칭인 Type Alias 도 마찬가지로 js코드로 변환 시 사라지니 유의)

인터페이스와 비슷한 역할을 하는 것이 클래스이며 js코드에도 남아있다. 

😎인터페이스를 바로 타입 가드로 사용할 수 있는 방법은 없기 때문에 클래스로 변환하여 사용
class CustomError extends Error {
  //response값이 있을수도 없을 수도 있기 때문에 "?""
  response?: {
    data: any;
  };
}
declare const axios: Axios;
(async () => {
  try {
    await axios.get();
  } catch (err: unknown) {
    if (err instanceof CustomError) {
      console.error(err.response?.data);
      console.log(err);
    }
  }
})();

-> 원래 interface이던 CustomError를 class로 변환하여 instanceof 를 사용할 수 있게 만들었다. 

if절의 instanceof 로 "타입 가드"를 할 수 있기 때문에 interface를 사용했을 때 as로 타입 단언하던 것은 불필요해진다. 

catch 문에서도 err 를 사용할 때 as를 쓰지않고 위처럼 "타입 가드"하는 것이 가장 베스트이다.
즉, unkown이 있을 때는 타입 가드를 적용해주는 것이 베스트
댓글