🤔 사용 목적만 봤을때는 그래서 제네릭이 왜 필요한지 확 와닿지가 않습니다.
그래서 제네릭을 활용 안했을때의 단점에 대해서 설명코자 합니다.
함수 중복 선언으로 인한 유지보수성의 저하
⇒ 동일한 기능을 하는 함수를 정의하고 싶지만, 파라미터의 type 한계점을 꼽을 수 있습니다.
즉 기존 타입정의 방식으로 정의한다면,
함수에 선언된 내용(기능)은 같지만 Param의 제한적 type으로 인해 파라미터의 타입만 다르고 기능은 동일한 불필요한 코드를 중복 작성하게 됩니다.
a
라는 변수에 hover 시, type으로 string | number 로 나옵니다. 그렇기 때문에 split()
이라는 string type을 지원하는 메소드를 인식하지 못하게 됩니다.
function 제네릭명<T>(파라미터: T) : T {}
function logText<T>(text: T): T {
console.log(text);
return text;
}
// 1. <T> : 어떤 type을 받을건지 정의 (제네릭 선언)
// 2. 그 T를 인자(text)로 넘긴다.
// 3. return할때도 해당 type으로 반환할 것을 선언
const str = logText<string>('abc');
str.split("");
const login = logText<boolean>(true);
logText
함수를 제네릭으로 선언하게 되면 <T>
에는 어떤 type이든지 들어올 수 있습니다.
이는 함수의 재사용성을 높여주고 유지보수성에도 효과적인 코드입니다.
따라서 Type을 string
으로 부여했다면 str
변수의 type은 string
으로 선언됩니다.
그리고 이에 따라 string type의 메소드를 지원합니다.
interface DropdownItem<T> {
value: T;
selected: boolean;
}
const emails: DropdownItem<string>[] = [
{ value: 'naver.com', selected: true },
{ value: 'gmail.com', selected: false },
{ value: 'hanmail.net', selected: false },
];
const numberOfProducts: DropdownItem<number>[] = [
{ value: 1, selected: true },
{ value: 2, selected: false },
{ value: 3, selected: false },
];
인터페이스를 제네릭으로 선언하는 것 역시 반복적으로 선언되는 인터페이스 구문을 줄이기 위함이다.
emails
와 numberOfProducts
모두 객체로 value와 selected를 값으로 전달받을때,
selected는 두 변수 모두 동일하게 boolean이지만
value에서 2가지로 분기된다. 이 부분을 활용하여 인터페이스를 제네릭화 할 수 있다.
따라서 위와 같이 value에 대해서 제네릭 T로 받게 되면 두 개의 변수에서 DropdownItem
인터페이스를 string 또는 number와 같이 유동적으로 사용할 수 있다.
interface lengthType {
length: number;
}
function logTextLength<T extends lengthType>(text:T): T {
text.length;
return text;
}
logTextLength('a');
logTextLength({ length : 10 });
정의된 타입을 이용한다 = 인터페이스를 활용하겠다.
먼저 Type을 명세한 interface를 선언합니다.
그리고 logTextLength
function에서 제네릭을 선언할 때, extends
를 통해 interface를 상속 받아 정의된 타입을 이용할 수 있습니다.
keyof
는 인터페이스의 속성 중 하나를 택해서 사용하고 싶을 때 사용합니다.
interface shoppingItem {
name : string;
price : number;
stock : number;
}
function getShoppingItemOption<T extends keyof shoppingItem>(itemOption : T): T {
return itemOption;
}
getShoppingItemOption("name");
shoppingItem
인터페이스의 속성들 중에 타입을 선택해서 제네릭을 선언할 수 있습니다.