TypeScript 제네릭 완전 정복: 실무에서 바로 쓰는 패턴
데브노트 편집팀·2026.07.06·7분 읽기
ADVERTISEMENT
TypeScript를 쓰다 보면 <T> 문법 앞에서 멈칫하게 됩니다. 제네릭은 타입을 값처럼 매개변수로 받는 기능입니다. any로 타입을 포기하지 않으면서, 함수·클래스를 여러 타입에 재사용하게 해줍니다.
any 대신 제네릭을 써야 하는 이유
// any: 타입 정보가 사라진다
function firstAny(arr: any[]): any { return arr[0]; }
const a = firstAny([1, 2, 3]); // a: any (자동완성·검사 없음)
// 제네릭: 입력 타입이 출력까지 이어진다
function first<T>(arr: T[]): T { return arr[0]; }
const b = first([1, 2, 3]); // b: number
const c = first(['a', 'b']); // c: string
핵심은 호출 시점에 T가 실제 타입으로 추론된다는 점입니다. 직접 first<number>(...)로 명시할 수도 있습니다.
extends로 제약 걸기, keyof로 키 안전하게
제네릭에 아무 타입이나 들어오면 곤란할 때 extends로 제약합니다.
// length를 가진 타입만 허용
function logLength<T extends { length: number }>(x: T): T {
console.log(x.length);
return x;
}
// 객체의 키만 안전하게 받기
function getProp<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
const user = { name: '철수', age: 20 };
getProp(user, 'name'); // string
getProp(user, 'xxx'); // 컴파일 에러: 'xxx'는 키가 아님
자주 쓰는 유틸리티 타입
| 유틸리티 | 역할 |
|---|---|
Partial<T> | 모든 속성을 선택적으로 |
Required<T> | 모든 속성을 필수로 |
Pick<T, K> | 일부 키만 추출 |
Omit<T, K> | 일부 키만 제외 |
Record<K, V> | 키-값 맵 타입 생성 |
type User = { id: number; name: string; email: string };
type UserUpdate = Partial<Omit<User, 'id'>>; // id 빼고 전부 선택적
마무리 체크리스트
- 타입이 입력→출력으로 흘러야 하면 any가 아닌 제네릭
- 제약이 필요하면
T extends ... - 객체 키 접근은
K extends keyof T로 안전하게 - 반복되는 타입 변형은 유틸리티 타입으로 간결하게
제네릭은 '재사용 + 타입 안전' 두 마리를 잡는 도구입니다. 패턴 몇 개만 익히면 코드의 안정성이 확연히 올라갑니다.
ADVERTISEMENT
함께 보면 좋은 글
프론트엔드· 6분
TypeScript 입문: 타입 기초부터 인터페이스, 제네릭까지
자바스크립트 개발자를 위한 TypeScript 입문 가이드입니다. 기본 타입, 인터페이스, 유니온, 제네릭까지 꼭 필요한 핵심 개념을 실전 코드로 빠르게 익혀보세요.
2026.07.01
프론트엔드· 7분
== vs ===, 그리고 NaN: 자바스크립트 동등 비교의 함정
느슨한 비교(==)의 암묵적 형변환이 만드는 버그, ===를 기본으로 써야 하는 이유, NaN·null·undefined 비교의 특이점을 예제로 정리합니다.
2026.06.05
프론트엔드· 7분
Next.js App Router: 서버 컴포넌트와 클라이언트 컴포넌트 제대로 나누기
App Router에서 가장 헷갈리는 'use client' 경계. 서버/클라이언트 컴포넌트의 차이와 데이터 패칭 위치, 흔한 실수를 실전 기준으로 정리합니다.
2026.07.08