TypeScript에서 함수 타입이란 매개변수의 타입 과 반환값의 타입 을 명시하는 것입니다.

기본적인 함수 타입

TYPESCRIPT
// 함수 선언문
function add(a: number, b: number): number {
  return a + b;
}

// 화살표 함수
const multiply = (a: number, b: number): number => a * b;

// 반환 타입 추론 — 명시하지 않아도 number로 추론됨
const subtract = (a: number, b: number) => a - b;

함수 타입 별칭

TYPESCRIPT
// 타입으로 함수 시그니처를 정의
type MathOperation = (a: number, b: number) => number;

const divide: MathOperation = (a, b) => a / b;
const modulo: MathOperation = (a, b) => a % b;

호출 시그니처(Call Signature)

TYPESCRIPT
// 함수이면서 속성도 가진 타입을 정의할 때
type DescribableFunction = {
  description: string;
  (arg: number): boolean;  // 호출 시그니처
};

function isEven(n: number): boolean {
  return n % 2 === 0;
}
(isEven as DescribableFunction).description = '짝수 판별';

선택적 매개변수와 기본값

TYPESCRIPT
// 선택적 매개변수 — ?를 붙이면 생략 가능
function greet(name: string, greeting?: string): string {
  return `${greeting ?? '안녕하세요'}, ${name}님!`;
}

greet('홍길동');              // '안녕하세요, 홍길동님!'
greet('홍길동', '반갑습니다'); // '반갑습니다, 홍길동님!'

// 기본값이 있으면 ?를 안 붙여도 생략 가능
function greetWithDefault(name: string, greeting: string = '안녕하세요'): string {
  return `${greeting}, ${name}님!`;
}

선택적 매개변수는 반드시 필수 매개변수 뒤에 와야 합니다.

나머지 매개변수(Rest Parameters)

TYPESCRIPT
function sum(...numbers: number[]): number {
  return numbers.reduce((acc, n) => acc + n, 0);
}

sum(1, 2, 3);       // 6
sum(1, 2, 3, 4, 5); // 15

// 튜플과 조합
function log(message: string, ...values: [number, boolean]): void {
  console.log(message, ...values);
}

log('결과:', 42, true);

void와 never 반환 타입

TYPESCRIPT
// void: 반환값이 없음 (undefined 반환)
function logMessage(msg: string): void {
  console.log(msg);
  // return undefined; // OK
}

// never: 함수가 절대 정상적으로 종료되지 않음
function throwError(message: string): never {
  throw new Error(message);
}

function infiniteLoop(): never {
  while (true) {
    // 영원히 실행
  }
}

면접 포인트: voidnever의 차이를 물어봅니다. void는 "반환값을 사용하지 않겠다"는 의미이고, never는 "이 함수는 정상적으로 끝나지 않는다"는 의미입니다.

함수 오버로드(Function Overload)

같은 함수 이름으로 ** 다른 매개변수 조합 **을 처리할 때 사용합니다.

TYPESCRIPT
// 오버로드 시그니처
function createElement(tag: 'div'): HTMLDivElement;
function createElement(tag: 'input'): HTMLInputElement;
function createElement(tag: 'a'): HTMLAnchorElement;

// 구현 시그니처
function createElement(tag: string): HTMLElement {
  return document.createElement(tag);
}

// 호출할 때 정확한 반환 타입을 얻음
const div = createElement('div');     // HTMLDivElement
const input = createElement('input'); // HTMLInputElement

오버로드 작성 규칙

TYPESCRIPT
// ✅ 오버로드 시그니처는 구현 시그니처보다 위에 선언
function format(value: string): string;
function format(value: number): string;
function format(value: string | number): string {
  if (typeof value === 'string') {
    return value.trim();
  }
  return value.toFixed(2);
}

// ❌ 구현 시그니처는 직접 호출할 수 없음
// format(true); // Error — boolean을 받는 오버로드가 없음

공부하다 보니 오버로드보다 ** 제네릭이나 유니온 **으로 해결할 수 있는 경우가 많더라고요. 오버로드는 매개변수 타입에 따라 반환 타입이 달라지는 경우에만 사용하는 것이 좋습니다.

this 타입

TYPESCRIPT
// 메서드에서 this 타입을 명시
interface User {
  name: string;
  greet(this: User): string;
}

const user: User = {
  name: '홍길동',
  greet() {
    return `안녕, ${this.name}`; // this가 User로 타입 체크됨
  },
};

// ❌ this 컨텍스트가 깨지면 에러
// const greetFn = user.greet;
// greetFn(); // Error: The 'this' context is not assignable

메서드 체이닝에서 this 타입

TYPESCRIPT
class QueryBuilder {
  private filters: string[] = [];

  where(condition: string): this {
    this.filters.push(condition);
    return this; // this를 반환 타입으로 — 서브클래스에서도 체이닝 가능
  }

  build(): string {
    return this.filters.join(' AND ');
  }
}

class AdvancedQueryBuilder extends QueryBuilder {
  orderBy(field: string): this {
    // where()가 AdvancedQueryBuilder를 반환하므로 체이닝 가능
    return this;
  }
}

const query = new AdvancedQueryBuilder()
  .where('age > 18')    // AdvancedQueryBuilder 반환
  .orderBy('name')      // AdvancedQueryBuilder 반환
  .where('active = true')
  .build();

콜백 함수의 타입

TYPESCRIPT
// 콜백 타입 정의
type Callback = (error: Error | null, data?: string) => void;

function fetchData(url: string, callback: Callback): void {
  try {
    const data = '결과 데이터';
    callback(null, data);
  } catch (e) {
    callback(e as Error);
  }
}

// 콜백의 반환 타입은 보통 void
// void 반환 타입은 반환값이 있어도 무시됨
type VoidCallback = () => void;
const cb: VoidCallback = () => 42; // OK — 반환값은 무시됨

정리

  • 함수 매개변수는 반드시 타입을 명시해야 하고, 반환 타입은 추론 가능하다
  • ?로 선택적 매개변수, 기본값으로 =을 사용한다
  • void는 반환값 없음, never는 정상 종료 불가를 의미한다
  • 오버로드는 매개변수에 따라 반환 타입이 달라질 때만 사용한다
  • this 타입으로 메서드 체이닝의 타입 안전성을 확보할 수 있다
댓글 로딩 중...