eatthefrog

타입스크립트 제네릭 본문

프론트엔드 노트

타입스크립트 제네릭

eater_forg 2025. 7. 8. 21:17

제네릭의 핵심은 "호출 시점에 타입이 결정되면 그 타입으로 고정"된다는 점이다.


제네릭의 타입 안정성 작동 방식:

function insertAtBeginning<T>(array: T[], value: T): T[] {
  return [value, ...array];
}

// 각 호출마다 T가 구체적인 타입으로 결정됨
const numbers = insertAtBeginning([1, 2, 3], 0);     // T = number로 고정
const strings = insertAtBeginning(['b', 'c'], 'a');   // T = string으로 고정

안정성이 지켜지는 이유:

  1. 호출 시점에 타입 체크가 엄격함:
// ❌ 에러 발생 - 배열은 number[]인데 value는 string
const result = insertAtBeginning([1, 2, 3], 'hello');

// ❌ 에러 발생 - 배열과 value의 타입이 일치하지 않음
const mixed = insertAtBeginning([1, 2], 'string');
  1. 반환값의 타입도 확실히 보장됨:
const numbers = insertAtBeginning([1, 2, 3], 0);
// numbers는 확실히 number[] 타입
numbers[0].toFixed(2); // ✅ 숫자 메서드 사용 가능
numbers[0].split();    // ❌ 에러 - 숫자에는 split이 없음

any와 비교해보면:

// any 사용 - 진짜 안전하지 않음
function insertAny(array: any[], value: any): any[] {
  return [value, ...array];
}

const result = insertAny([1, 2, 3], 'hello'); // 섞여도 에러 없음
result[0].toFixed(2); // 런타임 에러 발생 가능
result[0].split();    // 런타임 에러 발생 가능

제네릭의 진짜 의미:

  • 작성할 때는 유연하게 (어떤 타입이든 받을 수 있게)
  • 사용할 때는 안전하게 (한 번 정해진 타입으로 엄격하게)

즉, "여러 타입을 지원하지만, 한 번에 하나의 타입으로만 동작"하는 거죠. 이게 제네릭의 핵심이다.