Frontend/TypeScript

TypeScript Generic(Advanced)

개발자의 첫 걸음 2025. 11. 23. 10:00

안녕하세요. 오늘은 타입스크립트 제네릭의 응용편(실무 활용 중심)에 알아볼게요.

 

 

 

제네릭 응용편

 

이번 포스팅은 제네릭의 단순 <T>를 쓰는 수준을 넘어서 

 

"제네릭을 이용해 유연하면서도 안전한 타입 구조를 만드는 법"을 알아볼게요.

 

 

1. 유니온 타입(Union Type) + 제네릭 확장

type StringOrNumber = string | number;

function unionGeneric<T extends StringOrNumber>(value: T) {
  if (typeof value === 'string') {
    return value.toLowerCase();
  }
  return value; // 숫자는 그대로 반환
}

const result1 = unionGeneric('sTrInG'); // 'string'
const result2 = unionGeneric(1000);     // 1000

// ✅ 해설
// T extends StringOrNumber → T는 반드시 string 또는 number 중 하나여야 함.
// 즉, 제네릭에 “범위를 제한(제약)”을 건 것.
// 이렇게 하면 boolean, object 같은 타입은 컴파일 단계에서 거부됨.
// 코드 안에서 typeof value === 'string'으로 분기 처리 가능.

 

 

2. Partial <T> - 일부 속성만 수정

interface User {
  name: string;
  age: number;
}

type ObjectSignature = {
  [key: number]: User;
}

const users: ObjectSignature = {
  1: { name: '최광섭', age: 35 },
  2: { name: '권지애', age: 20 },
};

function UpdateUser(id: number, changes: Partial<User>) {
  const user = users[id];

  if (!user) {
    console.log('해당 id의 사용자는 없습니다.');
    return;
  }

  users[id] = { ...user, ...changes }; // 변경값 덮어쓰기
}

UpdateUser(1, { name: '이승아' }); // 이름만 수정
UpdateUser(2, { age: 15 }); // 나이만 수정
console.log(users);

// ✅ 해설
// Partial<User> : User의 모든 속성이 선택적(optional) 이 됨.
//	→ { name?: string; age?: number }

// 즉, 필요한 속성만 골라서 전달 가능.
// 실무에서 PATCH(부분 수정) 요청 구현 시 매우 자주 사용됨.

 

 

3. Readonly <T> - 읽기 전용 객체 생성

interface Person {
  name: string;
  age: number;
}

let user: Readonly<Person> = {
  name: '김철수',
  age: 25,
};

// user.age = 30; // ❌ 오류: 읽기 전용 속성
console.log(user.name); // 김철수

// ✅ 해설
// Readonly<T> : 모든 속성을 읽기 전용으로 변경.
//	→ 수정(=) 불가, 데이터 보호용 객체 만들 때 사용.

// 실무에서는 환경설정(config) 객체, 상수 데이터, 불변성 유지용으로 활용.

 

 

4. Omit <T, K> - 특정 속성 제거

interface Employee {
  id: number;
  name: string;
  age: number;
  position: string;
  address: string;
  phone: string;
}

type EmployeeForAccount = Omit<Employee, 'address'>;
type EmployeeForGeneral = Omit<Employee, 'address' | 'phone'>;

const salaryA: EmployeeForAccount = {
  id: 1,
  name: '최광섭',
  age: 35,
  position: '교육부',
  phone: '010-1111-1111',
};

const salaryB: EmployeeForGeneral = {
  id: 2,
  name: '김하늘',
  age: 28,
  position: '총무부',
};

// ✅ 해설
// Omit<T, K> : T에서 K 속성(들)을 제거한 새 타입 생성.
// 예: Omit<Employee, 'address'>
//	→ Employee에서 address 속성만 빠진 형태.

// 실무에서 부서별, 사용자 역할별 제한된 데이터 구조 정의 시 유용.
// (예: 개인정보는 HR만, 연락처는 관리팀만)

 

 

마지막으로 요약정리표예요.

 

제네릭 유틸리티 역할 특징 주요 사용 예시
Partial<T> 모든 속성을 선택적으로 변경 부분 수정용 (PATCH) Partial<User>
Readonly<T> 모든 속성을 읽기 전용으로 변경 데이터 불변성 유지 Readonly<Config>
Omit<T, K> 특정 속성을 제외한 새 타입 생성 필요없는 정보 제거 Omit<Employee, 'address'>
extends (제약) 제네릭 타입에 조건 추가 타입 범위 제한 <T extends string | number>

 

 

 

여기까지 제네릭의 응용편에 대해 알아봤는데요.

 

제네릭을 알아보면서 더 심화적으로 알아보면 어떨까 하고 찾아보고 같이 공유하고 싶어서 포스팅을 추가하게 됐어요.

 

제네릭 응용편을 잘 활용하셔서 재사용성과 코드 안정성을 극대화시켜보는 건 어떨까요?

'Frontend > TypeScript' 카테고리의 다른 글

Synchronous & Asynchronous & async / await  (0) 2025.11.25
TypeScript Generic  (0) 2025.11.21
TypeScript Interface  (0) 2025.11.21
TypeScript Type  (0) 2025.11.20
TypeScript(TS)  (0) 2025.11.19