Written by
Dohu Jeon
on
on
[Typescript] 제네릭 (Generics)
제네릭 (Generics)
제네릭은 재사용성이 높은 컴포넌트를 만들 때 자주 쓰인다.
특히, 한가지 타입보다 여러가지 타입에서 동작하는 컴포넌트를 생성하는데 사용된다.
제네릭은 아래와 같이 쓸 수 있다.
T
는 들어갈 타입이다.
function logText<T>(text: T): T {
return text;
}
// string
let txt:string = logText<string>('hi');
// number
let num:number = logText<number>(10);
제네릭 사용 이유
예를 들어 log를 찍고 리턴 함수가 있다.
아래는 string
type을 선언해서 string
만 받을 수 있다.
function logString(val: string):string {
console.log(val);
return val;
}
const aText = logString('a');
aText.charAt(0);
똑같은 기능을 가진 함수에 number
type을 넣을려면 같은 함수를 number
타입으로 따로 선언해야 된다는 불편함이 있다.
function logNumber(val: number):number {
console.log(val);
return val;
}
let bNum = logNumber(10);
bNum.toLocaleString();
그러면 Union type
으로 선언해서 둘 다 쓸 수도 있다.
function logText(val: string | number) {
console.log(val);
return val;
}
let cText = logText('c');
하지만 함수 후 받은 값을 쓸려면 타입이 아직 string or number
라 쓰기 제약이 많다.
![ctext값 string | number](/assets/img/typescript/ts-generics1.png “ctext값 string | number”) |
이럴때 아래처럼 Generics
를 이용하면 좋다.
string이면 함수 선언 할 때 string타입을 넣어 사용하고, number면 number타입을 넣어서 사용한다.
// generics선언
function logTextGenerics<T> (val: T): T {
console.log(val);
return val;
}
// string타입으로 선언
let stringTxt = logTextGenerics<string>('abcd');
stringTxt.split('');
// number타입으로 선언
let numTxt = logTextGenerics<number>(100);
numTxt.toLocaleString();
제네릭 인터페이스
인터페이스에도 제네릭이 사용가능하다.
// 인터페이스 제너릭 선언
interface DropdownItem<T> {
value: T;
selected: boolean;
}
// 인터페이스 string
let emailItem: DropdownItem<string>[] = [
{ value: 'naver.com', selected: true },
{ value: 'gmail.com', selected: false },
{ value: 'hanmail.net', selected: false },
];
// 인터페이스 number
let numberOfProductItem: DropdownItem<number>[] = [
{ value: 1, selected: true },
{ value: 2, selected: false },
{ value: 3, selected: false },
];
function logDropdownItem<T>(item: DropdownItem<T>): DropdownItem<T> {
console.log(item);
return item;
}
emailItem.forEach(function (email) {
let logStr: DropdownItem<string> = logDropdownItem(email);
});
numberOfProductItem.forEach(function (product) {
let logNum: DropdownItem<number> = logDropdownItem(product);
});
제네릭 타입 제한
타입 제한 1 - 배열
제네릭으로 들어오는 타입을 배열로 한정 시킬 수 있다.
배열안에 string, number 등등 타입들은 제네릭으로 추후에 선언 할 수 있다.
// 제네릭의 타입 제한 1
function logTextLength1<T>(text: T[]): T[] {
console.log(text.length);
text.forEach(function (text) {
console.log(text);
});
return text;
}
logTextLength1<string>(['hi', 'abc']);
logTextLength1<number>([1, 2]);
타입 제한 2 - 정의된 타입 이용 (extends)
interface를 extends를 하여 제네릭으로 들어오는 타입을 한정 시킬 수 있다.
아래의 LengthType 인터페이스에 number타입인 length속성을 넣었다.
함수인자에 제네릭 선언후 extends로 LengthType인터페이스를 상속하게 했다.
그러면 number타입인 length속성을 가진 타입만 들어올 수 있게 제한이 가능하다.
// 제네릭 타입 제한 2 - 정의된 타입 이용하기
interface LengthType {
length: number;
}
// extends: 기존에 정의된 interface를 확장할 때 쓰임
function logTextLength2<T extends LengthType>(text: T): T {
text.length;
return text;
}
logTextLength2('abc'); // string은 length속성을 내장하고있음
// logTextLength2(10); // 타입이 number인 length속성이 없어서 에러발생
logTextLength2([10, 20]); // 배열은 length속성을 내장하고있음
logTextLength2({length: 20, name: 'sd'}) //객체에 직접 length속성을 넣어주면 사용가능
Discussion and feedback