한 입 크기로 잘라먹는 타입스크립트
Search

제네릭 소개

 
section7/chapter0.ts 에서 실습과 함께 진행합니다.

제네릭이란

제네릭이란 함수나 인터페이스, 타입 별칭, 클래스 등을 다양한 타입과 함께 동작하도록 만들어 주는 타입스크립트의 놀라운 기능 중 하나 입니다.

제네릭이 필요한 상황

다음과 같이 다양한 타입의 매개변수를 받고 해당 매개변수를 그대로 반환하는 함수가 하나 필요하다고 가정하겠습니다.
코드를 불러오는 중 입니다 ...
다양한 타입의 매개변수를 제공받아야 하기 때문에 매개변수 value의 타입을 일단 any 타입으로 해 두었습니다. 물론 unknown으로 정의해도 괜찮습니다.
이 함수는 인수로 전달한 값을 그냥 그대로 반환하는 단순한 함수입니다. 따라서 변수 num에는 10이 저장되고 변수 str에는 “string”이 저장됩니다. 그런데 현재 num과 str의 타입은 any 타입이 됩니다. func 함수의 반환값 타입이 return 문을 기준으로 추론되었기 때문입니다.
이렇게 함수 호출 결과를 저장하는 num, str 등의 변수가 any 타입으로 추론되면 다음과 같은 문제점이 발생합니다.
코드를 불러오는 중 입니다 ...
num에는 분명 Number 타입의 값 10이 저장되어 있을 것이 분명합니다. 그러나 any 타입으로 추론되어 버렸기 때문에 toUpperCase 등의 String 타입의 메서드를 사용해도 타입스크립트가 오류를 감지하지 못합니다. 이 코드는 결국 실제로 실행하면 런타임 오류를 발생시키는 아주 위험한 상태가 됩니다.
자 그러면 이번에는 매개변수의 타입을 any 타입 말고 unknown 타입으로 정의해보겠습니다.
코드를 불러오는 중 입니다 ...
그러면 toUpperCase 같은 메서드 호출은 방지할 수 있습니다. 그러나 이번에는 또 다른 문제가 발생합니다. toFixed 같은 Number 타입의 메서드 호출도 함께 오류로 판단하게 됩니다.
따라서 num에 10이 저장될 것이 분명한데도 이 값을 사용하려면 다음과 같이 비 효율적으로 타입 좁히기를 이용해야 합니다.
코드를 불러오는 중 입니다 ...
사실 우리가 원하는 건 꽤나 간단합니다. 그냥 인수로 Number 타입의 값을 전달하면 반환 타입이 Number가 되고, 인수로 String 타입의 값을 전달하면 반환값의 타입도 String 타입이 되었으면 좋겠습니다. 그런데 지금까지 우리가 배운 타입스크립트 문법으로는 이 문제를 해결할 수 없습니다.
이럴때 바로 제네릭을 이용해야 합니다. func 함수를 제네릭 함수로 만들면 이 문제를 간단히 해결할 수 있습니다.

제네릭(Generic) 함수

제네릭(Generic) 함수란 무엇일까요? 일단 제네릭이란 일반적인 또는 포괄적인 이라는 뜻을 갖고 있습니다. 따라서 제네릭 함수는 일반적인 함수 또는 포괄적인 함수 정도로 해석할 수 있습니다. 이게 무슨 말 일까요?
제네릭과 그 의미가 거의 비슷한 단어가 하나 있습니다. 제네럴(General) 입니다. 제네럴은 영어권에서 종합병원을 이야기 할 때 사용되는 단어입니다. 영어권에서는 모든 병을 두루두루 포괄적으로 다루는 종합 병원을 제네럴 호스피탈(General Hospital)이라 부릅니다.
자 그러면 제네럴과 제네릭은 두루두루 다 적용될 수 있는, 또는 포괄적인 이런 뜻으로 의역해볼 수 있습니다. 따라서 제네릭 함수는 두루두루 모든 타입의 값을 다 적용할 수 있는 그런 범용적인 함수이다 정도로 이해할 수 있습니다.
다음과 같이 제네릭 함수를 선언할 수 있습니다.
코드를 불러오는 중 입니다 ...
함수 이름 뒤에 꺽쇠를 열고 타입을 담는 변수인 타입 변수 T를 선언합니다. 그리고 매개변수와 반환값의 타입을 이 타입변수 T로 설정합니다.
T에 어떤 타입이 할당될 지는 함수가 호출될 때 결정됩니다. func(10) 처럼 Number 타입의 값을 인수로 전달하면 매개변수 value에 Number 타입의 값이 저장되면서 T가 Number 타입으로 추론됩니다. 이때 T가 Number 타입으로 추론됩니다. 그럼 이때의 func 함수의 반환값 타입또한 Number 타입이 됩니다.
notion image
 
제네릭 함수를 호출할 때 다음과 같이 타입 변수에 할당할 타입을 직접 명시하는 것도 가능합니다.
코드를 불러오는 중 입니다 ...
위 코드의 흐름은 다음과 같습니다.
  1. T에 [Number, Number, Number] 튜플 타입이 할당됨
  1. 매개변수 value와 반환값 타입이 모두 튜플 타입이 됨
만약 위 코드에서 타입 변수에 할당할 타입을 튜플 타입으로 설정하지 않았다면 T가 number[] 타입으로 추론 되었을 것 입니다. 타입스크립트는 타입을 추론할 때 항상 일반적이고 좀 더 범용적인 타입으로 추론하기 때문입니다. 이렇듯 타입 변수에 할당하고 싶은 특정 타입이 존재한다면 함수 호출과 함께 꺽쇠를 열고 직접 명시해주는게 좋습니다. 그렇지 않은 대다수의 상황에서는 알아서 잘 추론되기 때문에 굳이 타입 변수를 설정하지 않아도 됩니다.
 
 
 
NEXT타입 변수 응용하기