Function Overload
overload signature
를 사용하여 함수를 다양한 방식으로 호출할 수 있음
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);
const d2 = makeDate(5, 5, 5);
const d3 = makeDate(1, 3);
- 함수를 호출할 때 하나의 overload만 고려함
function len(s: string): number;
function len(arr: any[]): number;
function len(x: any) {
return x.length;
}
len("");
len([0]);
len(Math.random() > 0.5 ? "hello" : [0]);
- 같은 인자 수와 같은 반환 타입을 가진 overload의 경우, overload가 아니라 union 타입을 쓰는 것이 좋음
function len(x: any[] | string) {
return x.length;
}
Do's and Don't
❌ Callback의 인자만 다른 overload를 분리해서 사용하지 않기
declare function beforeAll(action: () => void, timeout?: number): void;
declare function beforeAll(
action: (done: DoneFn) => void,
timeout?: number
): void;
✅ 모든 인자를 포함하는 callback을 사용하는 하나의 overload 사용하기
declare function beforeAll(
action: (done: DoneFn) => void,
timeout?: number
): void;
❌ 일반적인 overloads를 구체적인 overloads 전에 넣지 않기
- 이유 : 타입스크립트는 함수를 호출할 때 처음으로 맞는 overload를 고르므로, 더 일반적인 overload를 먼저 선언할 경우 그 이후 선언되는 overload가 감춰지고 부를수 없게 됨
declare function fn(x: unknown): unknown;
declare function fn(x: HTMLElement): number;
declare function fn(x: HTMLDivElement): string;
var myElem: HTMLDivElement;
var x = fn(myElem);
✅ 구체적인 overloads 이후에 일반적인 overload를 넣기
declare function fn(x: HTMLDivElement): string;
declare function fn(x: HTMLElement): number;
declare function fn(x: unknown): unknown;
var myElem: HTMLDivElement;
var x = fn(myElem);
❌ 뒤따르는 매개변수만 다른 여러 overloads를 쓰지 않기
interface Example {
diff(one: string): number;
diff(one: string, two: string): number;
diff(one: string, two: string, three: boolean): number;
}
✅ 가능하면 optional 매개변수를 사용하기
interface Example {
diff(one: string, two?: string, three?: boolean): number;
}
❌ 한 인자에서만 타입이 다른 overloads 쓰지 않기
- 이유 : 한번에 하나의 overload만 고려하기 때문에, 한 인자의 타입이 2개 이사인 경우 여러 overloads를 쓰기보다는 union 타입을 쓰는 것을 권장함
interface Moment {
utcOffset(): number;
utcOffset(b: number): Moment;
utcOffset(b: string): Moment;
}
✅ 가능하면 union 타입을 사용하기
interface Moment {
utcOffset(): number;
utcOffset(b: number | string): Moment;