함수를 구현하기 전, 함수가 어떤 타입으로 작동하는 지 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 타입을 명시하지 않아도 되는 경우가 있다!
type Add = (a:number, b:number) => number;
parameter a
와 b
가 number 타입이며, number 타입을 return하는 call signature
const add:Add = (a, b) => a + b
call signature를 적용할 경우, a와 b의 타입을 명시해 줄 필요없다.
서로 다른 여러 개의 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일 경우를 나눠줘야 에러없이 실행 가능하다.
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)
}
}
함수push
가 string
타입과 Config
타입을 받을 수 있도록, 두 개의 call signature를 가지고 있는 타입 Push
를 선언하였다.
if문에서는 config
가 string 타입이며, else문에서는 config
가 Config타입 객체!
지금까지 본 예시는 각각의 call signature가 타입이 다른, 동일한 개수의 parameter를 가졌었다.
❗️ 그러나 만약, 하나의 call signature는 2개의 parameter를 가지고, 다른 call signature는 3개의 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
}
이 경우, a
와 b
는 두 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
는 선택사항임을 알려줘야 한다.