1. 제너릭이란
- 함수에 타입도 파라미터로 부여할 수 있는 것을 말한다.
const getZeroIndex = (array: unknown[]) => {
return array[0]
}
let a= getZeroIndex([7,3])
console.log(a+1)
- 함수는 반드시 7를 return하는 것을 알고 있으나 array가 unknown 타입이므로 숫자 연산 시 에러를 뱉는다.
- 당연히 7라고 해서 unknown인 array배열 파라미터의 타입을 number로 바꿔주지는 않기 때문이다.
2. 사용
1) 기본
const getZeroIndex<MyType> = (array :MyType[]) :MyType => {
return array[0]
}
let a= getZeroIndex<number>([7,3])
console.log(a+1)
2) 제한
① extends
const getPlusOne<MyType> = (x :MyType) => {
return x + 1
}
getPlusOne<number>(7)
- 설령 호출함수에서 제너릭으로 number를 넘겨줬다고 하더라도 함수의 x는 에러를 띄울 것이다.
- 왜냐하면 함수 입장에서는 number가 아닌 string이 들어올 수도 있는 상황이기 때문이다.
- 이 때 제너릭으로 받을 타입을 number로 제한하면 되지 않을까?
const getPlusOne<MyType extends number> = (x :MyType) => {
return x + 1
}
getPlusOne<number>(7)
- interface의 extends는 복사 개념이었던 반면 제너릭에서의 extends는 제한의 개념이다.
- 일종의 narrowing을 한 것이다.
② custom 타입으로도 타입 파라미터의 제한 가능
interface LengthCheck{
length: number
}
const getPlusOne<MyType extends LengthCheck> = (x :MyType) => {
return x + 1
}
getPlusOne<number>(7)
- MyType이 LengthCheck의 속성을 가지고 있습니까? 라는 뜻이다.
- 즉 현재 함수 호출에서는 제너릭으로 number를 넘겨주고 있고 함수는 MyType 제너릭을 통해 이 number를 받는다.
- 그리고 함수는 받은 MyType을 파라미터 x에게 적용한다.
- 이 때 MyType이 length라는 속성을 가진 타입인지 확인한다.
- 파라미터 x는 MyType 제너릭을 타입으로 가지는데 그 것은 number이므로 number에는 length 속성이 없어 에러가 나고 있는 것이다.
- 만약 string이나 array라면 length 속성을 가지니까 에러가 안 날 것이다.