
제네릭은 타입을 고정된 값으로 명시하지않고 변수를 통해 언제든지 변할 수 있는 타입을 보다 유연하게 사용하게끔 한다. 리액트에서 컴포넌트에 props로 무엇이 올지 모르기때문에 generic을 사용하고 제네릭을 사용하면 재사용성이 높은 함수와 클래스를 생성할 수 있다.
const arrLength = (arr: number | string):number => {
return arr.length
}
const arr1 = [ 1, 2, 3 ]
const arr2 = [ "1", "2", "3" ]
arrLength( arr1 )
arrLengtn( arr2 )
위의 로직처럼 유니온을 이용해서 타입을 명시 할 수도 있지만 제네릭을 이용하면 더 깔끔한 타입지정이 가능하다.
const arrLength<T> = (arr: T[]):number => {
return arr.length
}
const arr1 = [ 1, 2, 3 ]
const arr2 = [ "1", "2", "3" ]
arrLength<number>( arr1 )
arrLengtn<string>( arr2 )
제네릭은 꺽쇠<>와 문자 T를 이용해서 표현하고 T는 변수명이라 생각하면 된다. 함수를 호출 할 때 <number>로 타입을 지정하면 T 부분이 number로 바뀌어 실행된다. 변수명은 관습적으로 T라고 지정되지만 Type이 되어도 상관없고 P가 되어도 상관은 없다.
interface Obj {
name: string,
phone: number,
option: any
}
const sumin: Obj {
name: "sumin",
phone: 01012345678,
option : "online"
}
const mango: Obj {
name: "mango",
phone: 01012345678,
option : true
}
위의 로직처럼 any타입도 제네릭을 이용해서 타입을 체크하여 컴파일가 오류를 찾을 수 있게 할 수 있다.
interface Obj<T> {
name: string,
phone: number,
option: T
}
const sumin: Obj<string> {
name: "sumin",
phone: 01012345678,
option : "online"
}
const mango: Obj<boolean> {
name: "mango",
phone: 01012345678,
option : true
}
타입이 지정되어있지 않은 값에 제네릭을 이용하여 타입을 지정해준다.
const arr<A, B> = (x: A, y: B): [A, B] => {
return [x, y]
}
const array1 = arr<string, number>("1", 2)
// or
const arr<A, B: string> = (x: A, y: B): [A, B] => {
return [x, y]
}
const array2 = arr<number>(1, "2")
const num = <T extends { firstNum: number; lastNum: number }>(obj: T) => {
return {
...obj,
phone: obj.firstNum + "-" + obj.lastNum,
}
}
num({ firstNum: 456, lastNum: 1234, lastNum2: 5678 })
지정한 타입 이외의 값이 들어오게 할때 generics 이용해서 확장할 수 있다.
function profileEdit<T>(profile: T) {
const url = "https://api.example.com/users/" + profile
return fetch(url)
.then((response) => response.json())
.catch((error) => console.error("Error:", error))
}
profileEdit<string>("info")
url 타입은 string으로 타입 추론이 된다.