데이터 형식에 의존하지 않고, 하나의 값이 여러 다른 데이터 타입들을 가질수 있는 기술에 중점두어 재사용성을 높일수 있다.
쉽게 말해서 제네릭이란 타입을 마치 함수의 파라미터처럼 사용하는 것 을 말한다.
// JavaScript
function logoText(text){
console.log(text);
return text
}
logoText('hello') // 문자열 hello
logoText(20) // 숫자 20
logoText(true) // 불린값 true
위의 함수를 보면 text라는 파라미터에 값을 받아 text를 반환해 주는데 어떤 값이 들어가더라도 그대로 반환해준다.
제네릭을 사용한 함수
//TypeScript
function logoText<T>(text: T):T {
console.log(text);
return text
}
logoText('hello') // ①
logoText<string>('hello') // ②
<T>
부분을 정해주지 않은경우 넘겨주는 파라미터를 반영해 준다.<T>
에 타입을 정의해줬을경우 해당 타입을 파라미터에 반영해 준다.타입을 다르게 받기 위해 중복선언을 하는 경우 유지보수 측면에서 효율적이지 못한 다는 단점이 있다.
function logoText(text:string){
console.log(text);
text.split('').reverse().join(' '); // 문자열이라 함수 사용이 가능하다.
return text
}
function logoNumber(text: number) {
console.log(text);
return text
}
logoText('a')
logoText(10) // error
logoNumber(10)
함수의 중복선언을 쉽게 접근 하는 방식중 하나는 유니온 타입을 이용한 방식이다.
function logoText(text: string | number) {
return text
}
const a = logoText('a');
a.split('') // error ①
①
유니온을 사용했을 경우 정해준 타입에 맞는 인자를 전달해 줄수 있지만 api를 사용할수 없다.
split
은 문자열에 사용하는 api함수 인데 변수 a
가 어떤타입인지에 대해서는 정해주지 않았기 때문에 오류가 난다.
같은함수에 제너릭을 이용하면 타입을 추론해 최종값을 반환해준다.
function logoText<T>(text:T):T {
return text
}
const str = logoText<string>('abc');
const num = logoText<number>(10)
str
mum
// 제네릭을 사용한 인터페이스
interface DropdownItem<T> {
value:T;
selected:boolean;
}
const emails: DropdownItem<string>[] = [
{ value: 'naver.com', selected: true },
//..
];
const numberOfProducts: DropdownItem<number>[] = [
{ value: 1, selected: true },
//...
];
function createDropdownItem<T>(item: DropdownItem<T> ) {
const option = document.createElement('option');
//...
return option;
}
// NOTE: 이메일 드롭 다운 아이템 추가
emails.forEach(function (email) {
const item = createDropdownItem<string>(email);
//...
});
function logoTextLength<T>(text: T): T {
console.log(text.length); // Error: T doesn't have .length
return text;
}
인자에 선언한 T
는 아직 어떤 타입인지 정의해 주지 않았기 때문에 length
에서 오류가 난다. 이럴때 해결하는 방법을 살펴보자.
function logoTextLength<T>(text:T[]):T[]{
console.log(text.length);
return text
}
제네릭 타입이 배열 이기 때문에 length
가 혀용된다.
interface lengthType {
length: number;
}
function logoTextLength<T extends lengthType>(text: T): T {
console.log(text.length);
return text;
}
logoTextLength(10) // error, 숫자는 length가 존재아지 않으므로
logoTextLength({length:0, value:'hi'}) // 동작
위와같이 작성하면 타입에 대한 강제는 아니지만 length
에 동작하는 인자만 넘겨 받을수 있다.
interface SoppingItem{
name:string;
price:number;
stock:number
}
function getShoppingItemOption<T extends keyof SoppingItem>(itemOption:T):T{
return itemOption
}
getShoppingItemOption('name')
keyof
속성을 사용하게 된다면 객체안에 있는 속성("name"|"price"|"stock"
)중 한가지만 받아 올수 있다.
ctr+space
getShoppingItemOption(ctr+space)
해당 함수에ctr+space
를 하게 되면 접근 가능한 인자속성을 알려준다.
참고
타입스크립트 핸드북
캡틴판교_타입스크립트 입문