Ch 03. 함수 타입과 오버로드
매개변수 타입, 반환 타입, 선택적 매개변수, 오버로드, 콜백 타이핑까지 한 번에 정리합니다.
기본 함수 타입
// 파일: src/function-basics.ts// 선언식function add(a: number, b: number): number { return a + b;}// 화살표 함수const multiply = (a: number, b: number): number => a * b;// 반환 타입 추론 — 간단한 함수는 생략 가능const subtract = (a: number, b: number) => a - b; // number로 추론
반환 타입은 명시하는 편이 좋습니다. 구현이 바뀌었을 때 시그니처가 보호됩니다.
선택적 매개변수와 기본값
// 파일: src/optional-params.ts// 선택적 매개변수: ?를 붙임 — 반드시 필수 매개변수 뒤에 위치function greet(name: string, greeting?: string): string { return `${greeting ?? "Hello"}, ${name}!`;}greet("Alice"); // "Hello, Alice!"greet("Bob", "Hi"); // "Hi, Bob!"// 기본값 — 선택적보다 더 명확function createUser(name: string, role: string = "viewer") { return { name, role };}createUser("Alice"); // { name: "Alice", role: "viewer" }createUser("Bob", "admin"); // { name: "Bob", role: "admin" }
기본값이 있으면 ?를 따로 쓸 필요가 없습니다. 기본값이 더 자기 문서화됩니다.
나머지 매개변수 (Rest Parameters)
// 파일: src/rest-params.tsfunction sum(...numbers: number[]): number { return numbers.reduce((acc, n) => acc + n, 0);}sum(1, 2, 3); // 6sum(10, 20, 30, 40); // 100// 앞에 고정 매개변수와 함께function logWithPrefix(prefix: string, ...messages: string[]): void { messages.forEach(msg => console.log(`[${prefix}] ${msg}`));}
함수 타입 표현
함수를 변수나 매개변수로 전달할 때 타입을 명시합니다.
// 파일: src/function-types.ts// 함수 타입 선언type Formatter = (value: number) => string;type Predicate<T> = (item: T) => boolean;const formatCurrency: Formatter = (v) => `$${v.toFixed(2)}`;const isPositive: Predicate<number> = (n) => n > 0;// 함수를 받는 함수function filter<T>(items: T[], predicate: Predicate<T>): T[] { return items.filter(predicate);}const numbers = [-3, -1, 0, 2, 5];const positives = filter(numbers, isPositive); // [2, 5]
콜백 타이핑
// 파일: src/callbacks.ts// 콜백 타입 정의type SuccessCallback = (data: string) => void;type ErrorCallback = (error: Error) => void;function fetchData( url: string, onSuccess: SuccessCallback, onError: ErrorCallback): void { // ...}fetchData( "/api/data", (data) => console.log(data), // data: string으로 자동 추론 (err) => console.error(err) // err: Error로 자동 추론);
콜백 매개변수 타입은 호출부에서 추론됩니다. 선언부에 타입을 정확히 써두면 사용자는 신경 쓰지 않아도 됩니다.
함수 오버로드
같은 이름의 함수가 다른 시그니처를 가져야 할 때 씁니다.
// 파일: src/overloads.ts// 오버로드 시그니처 (구현 없음)function format(value: string): string;function format(value: number, decimals: number): string;function format(value: Date): string;// 구현 시그니처 — 외부에서는 보이지 않음function format( value: string | number | Date, decimals?: number): string { if (typeof value === "string") return value.trim(); if (typeof value === "number") return value.toFixed(decimals ?? 2); return value.toISOString();}format(" hello "); // "hello"format(3.14159, 2); // "3.14"format(new Date()); // ISO 문자열
오버로드 시그니처는 위에서 아래로 순서대로 매칭됩니다. 구체적인 시그니처를 먼저 씁니다.
오버로드가 필요한 경우와 필요 없는 경우
// 파일: src/when-overload.ts// 오버로드 불필요 — 유니온으로 충분function echo(value: string | number): string | number { return value;}// 오버로드 필요 — 입력 타입에 따라 반환 타입이 달라질 때function parse(input: string): number;function parse(input: number): string;function parse(input: string | number): string | number { return typeof input === "string" ? Number(input) : String(input);}const n = parse("42"); // numberconst s = parse(42); // string
반환 타입이 입력에 따라 달라지는 경우가 오버로드의 핵심 사용처입니다.
정리
- 매개변수와 반환 타입은 명시하는 것이 원칙입니다.
- 선택적 매개변수보다 기본값이 더 명확합니다.
- 콜백 타입은 선언부에 정의하면 사용자가 타입을 쓸 필요가 없습니다.
- 오버로드는 반환 타입이 입력 타입에 따라 달라질 때만 씁니다.