함수 오버로드는 다양한 유형의 매개변수와 반환 값을 가진 단일 함수를 생성할 수 있도록 합니다. C#이나 Java와 같은 다른 언어에서는 동일한 이름을 가진 여러 함수를 정의할 수 있지만, 각기 다른 유형이나 인수의 수를 가질 수 있습니다. TypeScript는 타입 수준에서 시그니처 오버로드를 통해 이 메커니즘을 지원하지만, 함수 본체는 항상 하나여야 합니다.
문제는 JavaScript가 타입이나 매개변수 수에 대한 오버로드를 기본적으로 지원하지 않기 때문에 발생합니다. TypeScript의 등장으로 여러 함수 시그니처를 연속으로 선언하고 그에 대한 하나의 구현을 수동으로 분별하여 작동시키게 됩니다.
문제가 발생하는 이유는 선언한 시그니처와 일치하지 않으면, TypeScript는 함수 본체 내의 매개변수에 가장 일반적인 타입(모든 매개변수 타입의 결합)을 할당하게 되고, 프로그래머는 검사와 타입 가드를 수행해야 하기 때문입니다.
해결책: 명시적 시그니처에서 오버로드를 엄격하게 타입 지정하고, union types와 type guards를 적절히 활용하며, 동작을 정확하게 문서화합니다.
코드 예시:
function format(value: string): string; function format(value: number, locale: string): string; function format(value: any, locale?: string): string { if (typeof value === 'number') { return value.toLocaleString(locale); } return value.trim(); } format(' hello '); // 'hello' format(123456, 'ru-RU'); // '123 456'
주요 특징:
C#처럼 동일한 이름을 가진 여러 함수를 다른 본체로 선언할 수 있나요?
아니요. TypeScript(및 JavaScript)에서는 사실상 그 이름을 가진 단일 함수만 존재합니다. 오버로드는 컴파일러를 위한 타입 수준에서만 작동하며, 실제로는 함수 본체가 하나입니다.
가장 일반적인 매개변수를 가진 시그니처를 오버로드 시그니처 후에 구현하지 않으면 어떻게 되나요?
TypeScript는 컴파일 오류를 발생시킵니다. 항상 모든 가능한 오버로드 옵션을 포괄하는 구현 함수가 하나 존재해야 합니다.
function foo(a: string): string; function foo(a: number): number; // 본체 없음 — 오류
함수 본체 내에서 특정 시그니처에 특화된 속성을 사용할 수 있나요?
아니요, 타입 검사(type guard) 후에만 가능합니다. 그렇지 않으면 TypeScript는 현재 호출되고 있는 시그니처에 따라 이러한 속성을 직접 사용하는 것을 허용하지 않습니다.
function bar(x: string): number; function bar(x: number): number; function bar(x: string | number): number { if (typeof x === 'string') return x.length; return x * 2; }
보편적인 시그니처-구현을 추가하지 않음:
function sum(a: string, b: string): string; function sum(a: number, b: number): number; // 구현 없음 — 컴파일러 오류
장점:
단점:
표준에 따라 오버로드를 구현함:
function sum(a: string, b: string): string; function sum(a: number, b: number): number; function sum(a: any, b: any): any { return typeof a === 'string' && typeof b === 'string' ? a + b : a + b; }
장점:
단점: