제네릭은 여러 타입에서 사용할 수 있는
재사용 함수나 재사용 클래스를 정의할 수 있게 해주는 특수 구문이다
확실한 타입을 모를 때 사용하는데 TypeScript가 이를 유추하여 동작한다
< >
꺽쇠 안에 타입을 입력
const nums : Array<number> = [];
const colors : Array<string> = [];
< >
꺽쇠 안에 제네릭 이름 작성
주로 T, U, V 순서대로 사용한다
각각의 함수는 숫자, 문자열, 불린형을 반환하고 있다
하지만 이런식으로 같은 기능의 함수를 일일히 만드는 것은 굉장히 비효율적이다
any
를 사용하면 위에서 작성했던 코드들을 하나의 함수로 표현할 수 있지만
any
의 사용은 TypeScript의 취지와 어긋나고
입력한 타입과는 다른 타입이 반환될 수 있어서 이 코드 또한 적절하지 않다
이런경우에 제네릭을 사용해볼 수 있다
갑자기 <T>
는 뭐고 왜 타입 위치에 T
가 쓰인걸까?
<T>
이게 바로 제네릭을 사용하는 방법이다
< >
꺽쇠 안에 제네릭 이름 T를 작성하여 T
타입이 있다고 미리 선언을 하고,
item
의 타입과 함수가 반환할 타입이 T
라고 설정한 것이다
이렇게 하면 어떠한 타입의 값이 입력되더라도 같은 타입을 반환하게 된다
콘솔을 통해 확인할 수 있다
❓ 매개변수로 배열을 받고 그 배열 중 한개만을 랜덤으로 반환하는 함수를 만들어보자
✏️
① 함수 getRandom
의 매개변수로 T
형태의 배열을 받고 T
를 반환하도록 설정한다
② 랜덤으로 인덱스를 추출한다
③ list
배열에서 randomIdx
에 해당하는 요소를 반환한다
TypeScript는 <string>
<number>
<boolean>
등의 타입을 선언하지 않아도 추론할 수 있다
타입을 선언해도, 타입을 선언하지 않아도
모두 같은 형태를 나타내는 것으로 보아 타입추론이 일어난다는 것을 알 수 있다
하지만! 모든 제네릭 함수에 타입추론이 적용되는 것은 아니다
getElementById
, querySelector
같은 함수는 TypeScript가 실제 반환값의 타입을 제대로 추론할 수 없다
TypeScript는 다른 파일에 어떠한 요소가 있는지 모르기 때문에 이런 경우에는 타입을 명시해줘야 한다
타입이 없으면 Element
로 인식하기 때문에
<HTMLButtonElement>
, <HTMLInputElement>
등 정확한 타입을 명시해줘야 TypeScript가 제대로 인식할 수 있다
TSX는 TypeScript를 사용할 수 있는 JSX 파일이다 (= React + TypeScript)
TSX 파일에서 화살표 함수로 제네릭을 작성하는 경우에
타입 파라미터 뒤에 콤마(,)를 붙여줘야 한다 → <T,>
여러개의 제네릭을 가지려면 콤마(,) 뒤에 제네릭을 작성해주면 된다
어떤 타입을 반환하는지 작성해주지 않았는데
TypeScript는 merge
함수가 반환하는 값이 T와 U의 교차 타입이라고 추론한다
mergeObj
에 마우스를 올려보면
T는 문자열 객체, U는 문자열 배열의 객체라는 것을 알 수 있다
제네릭의 타입을 제한할 수 있다
<T extends 타입>
타입 파라미터 뒤에 extends
키워드를 붙이고 제한할 타입을 작성한다
기본적인 타입뿐만 아니라 인터페이스나 타입별칭 으로도 제한이 가능하다
ex1) 기본타입으로 제한하기 (object)
ex2) 인터페이스로 제한하기
제네릭의 기본값을 지정할 수 있다
지정한 기본값은 타입 파라미터를 특정하지 않았을 때만 개입한다
<T = 타입>
타입 파라미터 뒤에 =
를 붙이고 설정할 기본타입을 작성한다
지정된 기본값 ❌, 타입 파라미터 특정 ❌ → unknown이 된다
지정된 기본값 ⭕, 타입 파라미터 특정 ❌ → 기본값을 따른다
지정된 기본값 ⭕, 타입 파라미터 특정 ⭕ → 특정한 타입을 따른다
제네릭은 인터페이스와 함께 사용할 수 있다
<Person>
제네릭은 인터페이스 Person의 형태를 따르면 된다
따라서 매개변수 item
은 Person의 형태를 따라야하고
이 함수는 Person의 형태를 반환한다는 뜻이다
제네릭은 클래스와 함께 사용할 수 있다
각각의 인스턴스에는 매개변수 item
이 필요한데
songs
의 item
은 Song
클래스 형태를 따라야 하고
videos
의 itme
은 Video
클래스 형태를 따라야 하는 것을 알 수 있다