TypeScript

[TypeScript] TypeScript 제네릭 타입, 기본 개념부터 예제까지

배트리버 2024. 11. 21. 22:28

1. 제네릭이란?

제네릭은 다양한 타입 간 재사용성을 높이기 위해 사용하는 타입스크립트의 기능입니다. 코드를 작성할 때 미리 타입을 지정하지 않고, 필요한 시점에 타입을 결정하도록 하는 방식입니다.

 

2. 제네릭 사용법

2-1. 함수의 제네릭

제네릭을 함수에 적용하면, 다양한 타입의 매개변수나 반환 값을 처리할 수 있습니다.

function getIdentity<T>(value: T): T {
  return value;
}

// 사용 예시
const num = getIdentity<number>(42); // number 타입
const str = getIdentity<string>('Hello World'); // string 타입

 

2-2. 호출 시그니처의 제네릭

호출 시그니처에 제네릭을 적용하면 함수의 타입을 사전에 정의하고 제네릭으로 유연성을 높일 수 있습니다.

type GenericFunction = <T>(value: T) => T;

const identity: GenericFunction = <T>(value: T) => value;

console.log(identity<number>(123)); // 123
console.log(identity<string>('TypeScript')); // 'TypeScript'

 

2-3. 제네릭 클래스

클래스 내부에서도 제네릭을 활용하면 외부에서 전달된 타입에 따라 클래스의 동작을 유연하게 변경할 수 있습니다.

class DataStorage<T> {
  private storage: T[] = [];

  addItem(item: T): void {
    this.storage.push(item);
  }

  removeItem(item: T): void {
    this.storage = this.storage.filter((i) => i !== item);
  }

  getItems(): T[] {
    return [...this.storage];
  }
}

// 사용 예시
const textStorage = new DataStorage<string>();
textStorage.addItem('Hello');
textStorage.addItem('World');
textStorage.removeItem('Hello');
console.log(textStorage.getItems()); // ['World']

 

2-4. 제한된 제네릭

extends를 사용하면 제네릭 타입에 제약을 걸 수 있습니다.

function logLength<T extends { length: number }>(item: T): void {
  console.log(item.length);
}

// 사용 예시
logLength('Hello'); // 문자열의 길이: 5
logLength([1, 2, 3]); // 배열의 길이: 3

 

2-5. 확장된 제네릭

제네릭 타입 매개변수에 유니온 타입을 사용하거나 여러 타입 매개변수를 선언할 수 있습니다.

function mergeObjects<T extends object, U extends object>(obj1: T, obj2: U): T & U {
  return { ...obj1, ...obj2 };
}

// 사용 예시
const combined = mergeObjects({ name: 'John' }, { age: 30 });
console.log(combined); // { name: 'John', age: 30 }

 


3. 제네릭 활용 사례

1. API 응답 타입 지정

제네릭은 API 호출 결과를 처리할 때 자주 사용됩니다.

interface ApiResponse<T> {
  data: T;
  success: boolean;
}

function fetchData<T>(url: string): Promise<ApiResponse<T>> {
  return fetch(url).then((response) => response.json());
}

// 사용 예시
interface User {
  id: number;
  name: string;
}

fetchData<User[]>('/api/users').then((response) => {
  console.log(response.data); // User 배열
});

 

 

4. 제네릭의 잘못된 사용 예시

1. 가독성을 해치는 제네릭

제네릭이 필요하지 않은 곳에 남용하면 오히려 코드를 복잡하게 만듭니다.

//비추천
function add<T extends number>(a: T, b: T): T {
  return (a + b) as T;
}


//추천
function add(a: number, b: number): number {
  return a + b;
}

 

5. 제네릭을 사용할 때 주의점

1. TSX 파일에서 제네릭 사용

tsx 파일에서는 태그와 제네릭의 꺾쇠괄호를 혼동할 수 있어 에러가 발생합니다.

const identity = <T>(value: T): T => value; // TSX에서는 컴파일 오류 발생

const identity = <T extends unknown>(value: T): T => value; // extends 사용하기

 

제네릭은 타입스크립트의 강력한 기능으로, 코드 재사용성과 타입 안전성을 모두 충족할 수 있게 해줍니다. 그러나 필요 없는 곳에서 사용하면 가독성을 떨어뜨릴 수 있으니 적절한 상황에서 사용하는 것이 중요합니다 !!!