제네릭은 타입을 함수의 파라미터처럼 사용하는 것을 의미한다. 제네릭은 재사용성이 높은 컴포넌트를 만들 때 자주 사용한다. 한 가지 타입보다 여러가지 타입에서 동작하는 컴포넌트를 생성할 때 유용하다.
<aside>
💡 T
는 Type parameter의 약자로 관용적으로 사용한다. 꼭 T
를 사용해야하는건 아니다.
</aside>
아래 함수의 text
파라미터엔 hi
10
true
등 어떤 타입의 값이 들어가더라도 그대로 반환한다. 이렇게 모든 타입을 받을 수 있는 이유는 타입을 따로 지정하지 않았기 때문에 암묵적으로 any
타입이 돼서 그런 것이다.
function getText(text) {
return text;
}
any
타입은 타입 검사를 하지 않기 때문에 어떤 타입이 들어가고, 반환되는지 알 수 없다.
아래 함수는 제네릭 기본 문법이 적용된 형태다. 위 함수와 비슷하게 어떤 타입이든 파라미터로 넘길 수 있다.
function getText<T>(text: T): T {
return text;
}
함수를 호출할 때 아래처럼 타입을 직접 넘겨줄 수 있다. 아래 2가지 방법으로 호출할 수 있다.
getText<string>('hi') // 혹은 getText('hi')
getText<number>(10) // 혹은 getText(10)
getText<boolean>(true) // 혹은 getText(true)
getText<string>('hi')
코드로 함수를 호출했을 때 제네릭이 적용된 함수는 아래 모양과 같아진다. 함수를 호출할 때 제네릭 값으로 string
을 넘겼기 때문에 함수의 T
부분이 string
으로 적용된 것이다(정확히 말하면 함수를 호출할 때 넘긴 타입에 대해 타입스크립트가 추정할 수 있게 된 것)
// 파라미터, 반환값 모두 string
function getText<string>(text: string): string {
return text;
}
만약 함수 인자로 받은 문자열의 length
를 확인하고 싶다면 .length
메소드를 사용하면 된다. 하지만 아래처럼 ts(2339) 컴파일러 에러가 발생한다. 제네릭 함수 코드의 T
는 파라미터와 반환 값 타입에 any
를 지정한 것과 같은 동작을 한다. 컴파일러 입장에선 .length
속성이 없는 number
타입 등이 올 수 있는 것을 감안하여 .length
속성을 허용하지 않는 것이다.