타입스크립트3: Call Signatures, Overloading

윤뿔소·2023년 2월 8일
0

TS

목록 보기
1/5

시작하기 전에 인수(argument)와 매개변수(parameter)는 딱히 분리해서 쓰지 않았다. 나는 파라미터 자체의 타입을 설정하기에 파라미터를 기준으로 기술했다.

Call Signatures

함수를 어떻게 호출해야하는지, 어떤 타입으로 반환하는지 알려주는 단서
함수 이름 위에 커서를 올렸을 때 뜨는 파라미터 타입 정보리턴 타입 정보를 말한다.

// Shortcut 버전
type Add = (a:number, b:number) => number;

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

const add: Add = (a, b) => a + b;

이렇게 변수에 넣어서 해줄 수도 있다.

위처럼 해준다면 타입을 따로 넣는 구간과 실행할 구간을 따로 두어 보기 편해 관리하기도 편하니 좋다!
쓰는 법을 잊었다면 전과 비슷하게 파라미터에 타입을 명시하고 변수에 갖다대 시그니처를 볼 수 있다. 그거 복사해서 쓰면 꿀!

Overloading

Function(=Method) Overloading은 직접 작성하기보다 외부 라이브러리에 자주 보이는 형태로, 하나의 함수가 복수의 Call Signature를 가질 때 발생한다.
함수 이름은 같지만 함수의 인자가 다를 경우를 지원할 수 있는 방식

정적 타입 언어들도 지원하는 방식인 오버로딩을 TS도 접목시킬 수 있다.
Call Signature가 대표적이다.
그러면 하나의 함수가 서로 다른 여러 개의 Call Signature 가지고 있으면 어떻게 될까? TS는 헷갈려하며 뭐라한다. 이때 어떻게 해야할까?

예시

파라미터의 타입이 다르다면

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

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

조건을 만들어 분기 처리. 아래의 라이브러리에 실제로 적용한 사례를 보자

파라미터의 타입이 다르다면: Next.js의 Router

TS와 넥스트를 같이 쓰면 많이들 쓰는 방법이다. 넥스트에는 Router라는 기능이 있다. 페이지를 바꾸는 기능인데 그 예는 아래와 같다.

Router.push({
  path: "/home",
  state: 1
})

.push("/home")

아래 push는 추가적으로 보내는 것이다. TS 입장에서 봤을 땐 이상하다. object와 string 2가지를 받아서 타입을 설정하기 어려워진다. 그러면 TS가 싫어하는 any로 설정을 해줘야하나? 아니다!

그래서 오버로딩을 적용하고, 타입 별 분기를 나눌 조건을 만들어줘야한다.

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);
  }
};

위 처럼 타입에서 2개를 받아준다. 즉, 타입을 중첩시켜 오버로드가 일어나고, 그 조건에 따라 조건을 세워 분기를 만들면 타입도 설정되고 예외도 처리되며 이쁘게 만들 수 있다.

파라미터의 갯수가 다르다면

Router는 그 이상의 파라미터를 받아올 수도 있다. 즉, 파라미터의 개수가 달라질 수도 있다는 것. 그렇다면 호출 시그니처에 따라 갯수가 다르면 어떻게 할까?

// 시그니처만 봐도 a, b는 공통! c는 선택이란 걸 알 수 있다.
type Add = {
  (a: number, b: number): number;
  (a: number, b: number, c: number): number;
};
// c에 ?연산자를 붙이고 1번째 시그니처라면 따로 타입이 없으니 설정하자!
const add: Add = (a, b, c?: number) => {
  if (c) return a + b + c;
  return a + b;
};
// 둘 다 성공!
add(1, 2);
add(1, 2, 3);

사실 많이 있는 상황은 아니다. 하지만 알아놓으면 예외 처리의 달인이 될 것이고, TS의 강호가 될 것이다.

사담

이거 신기한 기술이다. 이렇게 할 수도 있구나. 솔직히 좀 귀찮긴 한데 일일이 예외 처리 해주면 에러가 진짜 안날 거 같다.
좀 더 생각해보니 시그니처만 봐도 어떤 것이 옵션이고 필수고 등등의 정보를 알 수 있을 거 같다. 신기방기

profile
코뿔소처럼 저돌적으로

0개의 댓글