TypeScript : 제네릭(generic)
제네릭이란?
함수의 매개변수처럼 타입을 매개변수로 넘기고 그 타입을 그대로 반환받는것을 의미 합니다.
function getText<T>(text: T) : T {
return text;
}
getText<string>('Hello');
T로 선언된 부분이 모두 string으로 치환됩니다.
제네릭 타입을 string으로 지정하였기 때문에 코드 작성시에도 string으로 추론합니다.
추론을 통해 string과 관련된 메소드의 안내를 받을 수 있습니다.
function getText<string>(text: string): string {
return text;
}
결과적으로 아래와 같이 선언된 것과 같습니다.
function getText(text: string): string {
return text;
}
왜 사용할까?
제일 큰 목적으로 코드 중복의 문제입니다.
funtion getText(text: string): string {
return text;
}
function getNumber(num: number): number {
return num;
}
위 함수는 매개변수로 받은 값을 그대로 리턴합니다.
기능은 동일하지만 타입이 달라 함수를 두 번 정의했습니다.
물론 any를 사용해도 되지만 any를 사용할 경우 타입스크립트를 사용하는 의미가 없어집니다.
인터페이스에서의 제네릭
interface Dropdown<T> {
value: T,
selected : boolean
}
var product: Dropdown<string> = {
value: 'Nike Shoes',
selected: false
}
var stock: Dropdown<number> = {
value: 250,
selected: false
}
extends
제네릭을 통해 특정 타입만 받고 싶을 때는 extends를 사용합니다.
function getText<T extends string>(text: T) {
return text;
}
// 숫자로된 length 속성을 가지는 제네릭
function withLength<T extends { length: number }>(value: T) {
return value.length;
}
keyof
keyof를 활용해 타입 제약도 가능합니다.
keyof는 특정 타입의 키 값을 추출해서 문자열 유니업 타입으로 변환해 줍니다.
type DeveloperKeys = keyof { name: string, skill: string }
const firstColumn: DeveloperKeys = "name"
function printKeys<T extends keyof { name:string; skill: string;}>(value: T) {
console.log(value);
}
printKeys('name');
function getKeyOf<T extends keyof { name: string, num: number }>(value: T) {
console.log(value);
}
주의점
function printText<T>(text: T) {
console.log(text.length)
}
printText<string>('Hello');
위 함수는 string으로 받아 제대로 출력될것처럼 보입니다.
실제로는 어떤 타입이 들어오지 모르므로 타입 추론이 되지 않습니다.
이때는 extends와 같은 타입 제약을 사용합니다.
function printText<T>(text: T[]) {
console.log(text.length)
}
printText<string>(['a','b','c']); // 3
printText<number>([100]); // 1
printText([true,false]); // 2
함수 매개변수 제네릭에 []을 붙여줘도 됩니다.
이때는 배열 형태의 데이터를 넣어야 합니다.
printText([true,false])에 boolean 타입이 선언되지는 않았지만 타입과 맞게 연결되어 있으면 선언되어 있는것처럼 동작 합니다.