Generics

임준형·2023년 6월 2일

TypeScript

목록 보기
6/6

제네릭이란?

제네릭(Generics)은 클래스 또는 함수에서 사용할 타입(Type)을, 그 클래스나 함수를 사용할 때 결정하는 프로그래밍 기법

제네릭이 왜 필요할까?

아래와 같이 TypeScript로 구현한 List 클래스는 일반적으로 특정 데이터 타입을 규정하지 않고, 어떤 타입이든 아이템으로 추가하거나, 추출할 수 있지만 특정 데이터 타입을 규정한 List 클래스를 사용하고자 할 때 제네릭을 사용

class List {  
  private _data: any[] = [];
  
  constructor(data: any[]) {
    this._data = data;
  }
  
  get data(): any { 
    return this._data; 
  }
  
  add(item: any): void { 
    this._data.push(item); 
  }
  
  remove(index: number): void { 
    this._data.splice(index, 1); 
  }
  
  item(index: number): any { 
    return this._data[index]; 
  }
  
  clear(): void { 
    this._data = []; 
  }
}

사용법

이름 뒤에 <T>를 붙임 T는 관용적인 식별자로 다른 이니셜을 사용해도 무방

제네릭을 사용하여 위 List클래스를 재정의한다면 아래와 같이 바꿀 수 있음

class List<T> {  
  private _data: T[] = [];
  
  constructor(data: T[] = []) {
    this._data = data;
  }
  
  get data(): T[] { 
    return this._data; 
  }
  
  add(item: T): void { 
    this._data.push(item); 
  }
  
  remove(index: number): void { 
    this._data.splice(index, 1); 
  }
  
  item(index: number): T { 
    return this._data[index]; 
  }
  
  clear(): void { 
    this._data = []; 
  } 
}

List클래스에 string을 담고자 한다면, 클래스를 통해 객체를 생성하는 코드에 제네릭 타입 변수 값을 <string> 으로 설정해 사용

const stringList = new List<string>();

stringList.add("a");

stringModel.add(2018); // [오류]

설정된 타입이 아닌 다른 타입이 아이템이 사용 되면 컴파일 과정에서 오류 메시지를 출력

제네릭과 함수

함수도 클래스와 마찬가지로 제네릭 적용가능
TypeScript제네릭을 사용하여 외부에서 특정 타입을 지정할 수도 있도록 구현 하면, 사용자가 함수 호출 시 지정한 타입으로 한정할 수 있어 보다 사용 하기 좋아짐

function getItemArray<T>(arr:T[], index:number):T {
  return arr[index];
}

function pushItemArray<T>(arr:T[], item:T):void {
  arr.push(item);
}


const potatoChip_materials = ['어니언'];

getItemArray(potatoChip_materials, 0);
pushItemArray(potatoChip_materials, '사워크림');

만약 함수 호출 과정에서 전달된 타입과 다른 경우가 발생하면 TypeScript는 컴파일 과정에서 오류 발생

const potatoChip_materials = ['어니언'];

pushItemArray<number>(potatoChip_materials, 999); // [오류]

멀티 타입 설정

함수 또는 클래스에서 멀티 타입 변수 활용가능

type pairArray = [any, any][];

function pushPairItem<T, M>(arr: pairArray, item: [T,M]): pairArray {
  arr.push(item);
  return arr;
}

const data: pairArray = [];

pushPairItem<boolean, string>(data, [false, "false"]);
pushPairItem<number, string>(data, [2019, "이천십구년"]);

타입 변수 상속

제네릭 타입 변수는 기존의 타입 변수 상속가능
타입을 제한해야 할 때

특정 타입(기본타입, 클래스, 인터페이스 등)을 <T extends [...]>의 방식으로 상속

function add<T extends Type>(a: T, b: T) {
  return a + b;
}

add메서드의 TType의 모든 속성을 이전받고, 제네릭 함수/인터페이스/클래스는 T의 모든 구조를 가지고 있어야 한다.

0개의 댓글