Function Overloads
Function Overloads(함수 오버로드)
1. 오버로드란?
같은 이름의 함수를 여러개 정의 하는 것을 오버로딩
이라고 한다.
2. 오버로딩 조건
모든 함수를 오버로딩 할 수 있는것은 아니다.
오버로딩을 사용하기 위해서는 아래 조건을 반드시 만족해야 한다.
-
함수 이름이 같아야 한다.
-
매개변수의 개수 또는 타입이 달라야 한다.(매개변수의 순서는 같아야한다.)
또한, 매개변수의 개수 또는 타입이 다르다면 다른 리턴타입을 사용해서 선언할 수도 있다.
함수의 이름이 같더라도 매개변수가 다르면 서로 다르게 사용할 수 있기 때문에 오버로딩을 할 수 있다.
함수의 매개변수의 개수, 타입만 다르고 비슷한 코드가 반복 실행된다면 오버로딩을 사용해서 코드의 중복을 줄이고 코드의 재사용성을 높일 수 있을 것 같다.
3. 예제코드
아래 예제코드는 날짜를 각기 다른 매개변수로 받아 어떠한 로직을 처리하고 Date타입을 리턴하는 함수이다.
각각의 함수에서 비슷한 코드가 반복될 수도 있으며 같은 값을 리턴해주고 있는것을 확인해 볼 수 있다.
아래의 코드를 하나의 함수로 오버로딩 시켜보자.
// 오버로딩 전
function makeDate1(timestamp: number): Date {
// ...
return new Date(timestamp)
}
function makeDate2(m: number, d: number, y: number): Date {
// ...
return new Date(y, m, d)
}
아래와 같이 매개변수의 타입, 개수가 다른 makeDate함수를 먼저 선언하고,
각 파라미터 타입에 대응하는 코드를 작성해서 하나의 함수 내에서 구체적인 로직을 작성하고 있는것을 확인할 수 있다.
또한 선언되지않은 함수를 호출할때는 아래와 같이 오버로드의 매개변수가 잘못되었다는 에러가 나타나는것을 확인할 수도 있다.
// 오버로딩 후
// 선언
function makeDate(timestamp: number): Date
function makeDate(m: number, d: number, y: number): Date
// 구현
function makeDate(mOrTimestamp: number, d?: number, y?: number): Date {
// ...
if (d !== undefined && y !== undefined) {
return new Date(y, mOrTimestamp, d)
} else {
return new Date(mOrTimestamp)
}
}
// 호출
const d1 = makeDate(12345678) // OK
const d2 = makeDate(5, 5, 5) // OK
const d3 = makeDate(1, 3)
// Error: No overload expects 2 arguments, but overloads do exist that expect either 1 or 3 arguments
또 다른 예로 아래 코드는 문자열, 문자열 배열을 받고 각각의 길이를 리턴하는 함수이다.
아래와 같이 선언, 구현된 함수만 놓고 보면 코드에 문제는 없어 보인다..
// 선언
function len(s: string): number
function len(arr: string[]): number
// 구현
function len(x: any) {
return x.length
}
// 호출
len('') // OK
len(['0']) // OK
len(Math.random() > 0.5 ? 'hello' : ['0']) // Error
위의 코드를 다시 한번 확인해보자.
string타입, string배열 타입인 매개변수에는 길이를 구하는 .length를 사용할 수 있기 때문에 정상적으로 작동할 것 같다..
그러나 TypeScript는 단일 오버로드에 대한 함수 호출만 확인할 수 있기 때문에 문자열이나 배열 일 수 있는 값으로 이를 호출할 수 없다고 한다.(호출부분에서 에러가 나는것을 확인할 수 있음.)
위의 예제에서 확인할 수 있듯이 len함수는 매개변수 타입이 다르기 때문에 오버로드가 될 것 처럼 보였지만 에러가 나는것을 확인 할 수 있다.
이러한 문제 때문인가? 타입스크립트에서는 함수오버로드를 사용하는것 보다 유니온 타입을 사용하는 것이 더 간단하고 유연하게 다양한 매개변수 타입을 처리할 수 있기 때문에 가능한 경우 유니온 타입을 선호하는 것이 좋다고 표현하고 있다.
아래와 같이 유니온 타입으로 함수를 수정해보면 정상적으로 작동하는것을 확인할 수 있다.
function len(x: string[] | string) {
return x.length
}
// 호출
len('') // OK
len(['0']) // OK
len(Math.random() > 0.5 ? 'hello' : ['0']) // OK