제네릭은 C#이나 Java와 같은 언어에서 재사용 가능한 컴포넌트를 만들기 위해 사용하는 기법
즉, 변수나 인수에 타입을 정해주는 Concrete같이 딱딱한 기법과 달리 어떤 타입을 쓸지 정해주지 않고 그 타입에 대해 어떤 변수를 넣어주냐에 따라 결정되는 유연한 기법
any를 사용하면 아래와 같은 경우에도 에러가 발생하지 않는다
type SuperPrint = {
(arr: any[]): any
}
const superPrint:SuperPrint = (arr) => arr[0]
let a = superPrint([1, "b", true]);
a.toUpperCase(); // pass
Generic의 경우 에러가 발생해 보호받을 수 있다
WHY ? Call Signature를 concrete type으로 하나씩 추가하는 형태이기 때문!
// 방법 1
type SuperPrint = {
(arr: T[]): T
}
const superPrint: SuperPrint = (arr) => arr[0]
let a = superPrint([1, "b", true]);
a.toUpperCase(); // error
// 방법 2
type SuperPrint = {
(arr: T[], x: M): T
}
const superPrint: SuperPrint = (arr, x) => arr[0]
let a = superPrint([1, "b", true], "hi");
// 방법 3
function map<T>(array:T[], callback:(...args:any[]) => any;) {
const result = [];
for(const element of array){
result.push(callback(element));
};
return result;
}
map<number>([1,2,3,4], x => x + 1); // Good
map<string>(["hello", "world"], x => x.toUpperCase());