
🚀 "어떤 타입이 들어올지 모르지만, 나중에 사용할 때 정할 수 있도록 하는 기능"
🚀 "같은 코드로 여러 타입을 처리할 수 있도록 만들어주는 것"
function doubleNumber(num: number): number {
return num * 2;
}
console.log(doubleNumber(5)); // 10
✅ 여기서 num의 타입이 숫자(number)로 고정되어 있다.
즉, doubleNumber("hello") 같은 걸 하면 오류가 남 !!
그런데 숫자뿐만 아니라 문자열도 두 배로 만들고 싶다면?
제네릭을 사용하면 타입을 미리 정해두지 않고 나중에 받을 수 있다.
function printValue<T>(input: T) {
console.log(input);
}
//함수를 호출하는 예제
//<>내부에 원하는 type을 입력해준다.
printValue<string>("hello");
printValue<number>(7)
function double<T>(value: T): T {
return value;
}
console.log(double<number>(5)); // 5
console.log(double<string>("hello")); // "hello"
✅ 여기서 T가 타입을 나타내는 변수이다!!!!!!
✅ double(5)를 하면 T가 number로 결정되고,
✅ double("hello")를 하면 T가 string으로 결정된다.
<T> 를 이용하여 매개변수의 타입과 리턴 타입이 동일하도록 만들어줄 수 있다.function helloGeneric<T>(message: T): T {
return message;
}
// 추론
helloGeneric('Mark');
helloGeneric(39);
helloGeneric(true);
// 지정
helloGeneric<string>('Mark');
helloGeneric<number>(39);
helloGeneric<boolean>(true);
✅ 제약 조건은 제너릭 T는 숫자 또는 문자여야 한다는 것이다.
즉, 제네릭을 쓰면 함수가 여러 타입을 처리할 수 있음 !!
제네릭에 조건을 두어 사용하고 싶다면 extends 키워드로 제약조건을 걸 수 있다.
아무 객체가 되어도 상관없지만 일단은 객체여야한다는 조건
interface Lengthy {
length: number;
}
function countAndDescribe<T extends Lengthy>(element: T): [T, string] {
let descriptionText = 'Got no value';
if (element.length === 1) {
descriptionText = 'Got 1 element';
} else if (element.length > 1) {
descriptionText = `Got ${element.length} element`;
}
return [element, descriptionText];
}
function merge<T extends object, U extends object>(objA: T, objB: U) {
return Object.assign(objA, objB);
}
🚀 왜 제네릭을 사용할까?
1. 같은 코드로 여러 타입을 사용할 수 있어서 재사용성이 좋다.
2. 코드를 더 안전하게 사용할 수 있다. (잘못된 타입이 들어오면 에러 발생)
3. 유지보수가 쉬워진다. (중복되는 함수를 여러 개 만들 필요 없음)