[TypeScript] FUNCTIONS #3.0 - #3.1

uxolrv·2022년 12월 14일
1

nomadCoder - TypeScript

목록 보기
4/9
post-thumbnail

📌 Call Signatures

함수를 구현하기 전, 함수가 어떤 타입으로 작동하는 지 Call Signature를 통해 선언할 수 있음


// function add(a: number, b: number): number
const add = (a:number, b:number) => a + b

함수에 마우스 호버 시, 나타나는 function add(a: number, b: number): number 이 부분이 바로 Call Signature!

이 경우 함수 add의 return 타입이 number일 것이라고 TypeScript가 추론하였으므로, return 타입을 따로 명시하지 않아도 된다.

⇒ 반드시 return 타입을 명시하지 않아도 되는 경우가 있다!



🔎 함수의 call signature 타입을 만드는 방법

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

parameter ab가 number 타입이며, number 타입을 return하는 call signature



🔎 call signature 타입 적용

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

call signature를 적용할 경우, a와 b의 타입을 명시해 줄 필요없다.








📌 Overloading

서로 다른 여러 개의 call signature를 가지고 있는 함수를 만드는 것

TypeScript에서는 같은 이름을 가진 함수를 여러 개 정의할 수 있다.
이때, 같은 함수명에 인자가 다른 여러 버전의 함수를 만드는 것을 함수의 오버로딩이라고 한다.

실제로 오버로딩된 함수를 직접 작성할 일은 많지 않지만, 외부 라이브러리에서 오버로딩을 많이 사용하므로 알아두기!


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

위에서 작성하였던 call signature는 이렇게도 작성이 가능하다.
이는 오버로딩을 위한 call signature 작성법!


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

const add: Add = (a, b) => a + b
// Err: Operator '+' cannot be applied to types 'number' and 'string | number'

call signature를 위와 같이 작성할 경우, b가 string일 수도, number일 수도 있기 때문에 에러가 발생한다.


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
}

b가 string일 경우와 number일 경우를 나눠줘야 에러없이 실행 가능하다.



🔎 실제 프레임워크에서 볼 수 있는 오버로딩 예시 : Next.js

React.js의 프레임워크인 Next.js에서는 Router로 페이지를 나눌 수 있다.

Router.push("/home")

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

Router.push()의 인자로는 string 타입의 path 값이 올 수도 있으며, object 타입으로 path와 추가적인 값을 전달할 수도 있다.

string 으로도 보낼 수 있고, object로도 보낼 수 있는 이 경우가 바로 오버로딩이 발생하는 경우!


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

type Push = {
  (path: string): void // void는 아무것도 리턴하지 않는 것
  (config: Config): void
}


// (parameter) config: string | Config
const push: Push = (config) => {
  if (typeof config === 'string') {
    console.log(config)
  } else {
    console.log(config.path, config.state)
  }
}

함수pushstring 타입과 Config 타입을 받을 수 있도록, 두 개의 call signature를 가지고 있는 타입 Push를 선언하였다.

if문에서는 config가 string 타입이며, else문에서는 config가 Config타입 객체!



🔎 각각의 call signature들이 다른 개수의 parameter를 가지고 있을 때

지금까지 본 예시는 각각의 call signature가 타입이 다른, 동일한 개수의 parameter를 가졌었다.

❗️ 그러나 만약, 하나의 call signature2개의 parameter를 가지고, 다른 call signature3개의 parameter를 가진다면?


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

// Err!
const add: Add = (a, b, c) => {
  return a + b
}

이 경우, ab는 두 call signature에 공통적으로 존재하는 parameter이고, c는 하나의 call signature에만 존재하는 parameter이다.

add 함수를 사용할 때 a, b를 넣을 수도 있고, a, b, c를 넣어줄 수도 있다.

⇒ ✨ c는 옵션!!


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

const add: Add = (a, b, c?:number) => {
  if (c) return a + b + c
  return a + b
}

이러한 경우, 추가적으로 c의 타입을 지정하고, c는 선택사항임을 알려줘야 한다.








profile
안녕하세연🙋 프론트엔드 개발자입니다

0개의 댓글