본문 바로가기
Front-End/Typescript

Overloading

by developerDoorold 2022. 12. 16.

문가가 공부한 기록입니다. 부정확한 내용은 편히 지적 부탁드립니다.


 

 

 개발을 하면서 실제로 많은 오버로딩된 함수를 직접 작성하진 않을 것이다. 그 대신 다른 사람들이 만든 외부 라이브러리를 사용할 텐데 이런 패키지와 라이브러리들은 오버로딩을 엄청 많이 사용한다. 그래서 우리는 오버로딩이 어떻게 생겨먹은 놈인지 알고 있어야 한다.


type Add = (a: number, b: number) => number;

위 코드를 우리는 Call signature라고 부르기로 했다. 우리가 타입스크립트에게 이 함수가 어떻게 호출되는지 설명해주는 부분이다.(파라미터의 타입은 무엇인지, 함수의 리턴 타입은 무언인지!) 위와 같은 방식은 Call signature를 만드는 가장 간단하고 빠른 방법이다. 우리는 아래와 같은 방식으로도 Call signature를 만들 수 있다.

 

type Add = {
  (a: number, b: number): number;
};

위는 Call signature를 좀 길게 작성하는 방법이며 이런 방법이 존재하는 이유는 오버로딩 때문이다. 그럼 오버로딩은 무엇인가?

 

 

오버로딩은 함수가 여러 개의 Call signature를 가지고 있을 때 발생한다.

type Add = {
  (a: number, b: number): number;
  (a: number, b: string): number;
};

// b가 string도 될 수 있고 number도 될 수 있기에 a와 b를 더할 수 없다고 타입스크립트는 불평한다.
const add: Add = (a, b) => a + b;

 바보 같은 예시지만 Add 함수는 두 가지 방법으로 호출할 수 있다. 타입스크립트는 파라미터 a는 number 타입으로, 파라미터 b는 string 또는 number 호출할 수 있음을 파악하고 있다. 그리고 b가 string도 될 수 있고 number도 될 수 있기에 a와 b를 더할 수 없다고 타입스크립트는 불평한다.

 

const add: Add = (a, b) => {
  if (typeof b === "string") return a;
  return a + b;
};

 코드를 위와 같이 수정할 경우 타입스크립트는 만족하고 에러를 주머니 속으로 다시 넣어둘 것이다. 말했지만 이것은 매우 바보 같은 예시이다. 왜냐하면 이건 매우 매우 소수의 함수만 이런 식으로 처리할 수 있기 때문이다. 즉 아무 의미가 없다. 하지만 오버로딩의 핵심을 보여주고 있다. 이제 실제로 개발을 하며 겪을만한 예시를 보자. 

 

// object 방식
Router.push({
  path: "home",
  state: 1,
  // 추가 정보
});

// string 방식
Router.push("/home")

 NextJS에서의 라우팅 코드이다. 위 두 가지 방식은 모두 잘 작동하며 /home 경로를 요청했을 때 home 페이지로 이동시켜줄 것이다. 이를 구현한 코드는 아래와 같다.

 

type Config = {
  path: string;
  state: object;
};

type Push = {
  (path: string): void;
  (config: Config): void;
};

const push: Push = (config) => {
  if (typeof config === "string") {
    console.log(config);
  } else {
    console.log(config.path, config.state);
  }
};

우리는 지금까지 Call signature가 같은 개수의 파라미터를 요구하는 경우만을 살펴봤다. 이제는 파라미터 수가 서로 다른 경우를 알아보자. 

 

type Add2 = {
  (a: number, b: number): number;
  (a: number, b: number, c: number): number;
};

// 타입스크립트가 불편해한다.
const add2: Add2 = (a, b, c) => {
  return a + b;
};

위에서 타입스크립트가 불편을 표시하는 이유는 보이듯 다른 개수의 파라미터를 가지기 때문이다. 다른 개수의 파라미터를 가지게 되면 나머지 파라미터 또한 타입을 지정해주어야 한다. 여기 c 파라미터는 옵션 같은 것이다. 위 Call signature가 말해주고 있다. Add2를 부를 때는 a와 b를 부를 수도 있고, 또는 a, b, c를 부를 수도 있다. 이것이 의미하는 것은 기본적으로 c는 선택적이라는 것이다. 그래서 우리는 무엇을 해주어야 하는가? => c 파라미터의 타입을 명시하고 선택사항이라는 것을 알려주어야 한다. 

 

// 여기에 c는 아마도 number일 것이라는 것을 알려주는 것이다. 
const add2: Add2 = (a, b, c?: number) => {
  if (c) return a + b + c;
  return a + b;
};

console.log(add2(1, 2)); // 3
console.log(add2(1, 2, 3)); // 6

 

+참고자료

https://nomadcoders.co/typescript-for-beginners/lectures/3674

댓글