8장. JSX에서 TSX로
리액트 컴포넌트의 타입
- ReactElement, ReactNode, JSX.Element 활용하기
- ReactElement
- JSX의 createElement 메서드 호출로 생성된 리액트 엘리먼트를 나타내는 타입
- JSX.Element 대신에 ReactElement를 사용하여 추론 관점에서 더 유용하게 활용됨
- ReactNode
- 리액트의 render 함수가 반환할 수 있는 모든 형태
- prop으로 리액트 컴포넌트가 다양한 형태를 가질 수 있게 하고 싶을 때 유용하게 사용됨
- JSX.Element
- ReactElement의 특정 타입으로 props와 타입 필드를 any로 가지는 타입
- 리액트 엘리먼트를 prop으로 전달받아 render props 패턴으로 컴포넌트를 구현할 때 유용하게 활용됨
- ReactElement
- 클래스 컴포넌트와 함수 컴포넌트에서의 ref
- 클래스 컴포넌트 : ref된 객체는 마운트된 컴포넌트의 인스턴스를 current 속성 값으로 가짐
- 함수 컴포넌트 : 생성된 인스턴스가 없음 ⇒ ref에 기대한 값이 할당되지 않음
- 이러한 제약을 극복하고 함수 컴포넌트에서도 ref를 전달받을 수 있도록 도와주는 것이 바로 React.forwardRef 메서드
- forwardRef의 제네릭 인자 - 첫 번째는 ref에 대한 타입 정보, 두 번째는 props에 대한 타입 정보
- 함수 컴포넌트의 props로 ref를 포함하는 타입을 사용하게 되면, 실제로는 동작하지 않는 ref를 받도록 타입이 지정되어 예기치 않은 에러가 발생할 수 있음 ⇒ HTML 속성을 확장하는 props를 설계할 때는 ComponentPropsWithoutRef 타입을 사용하여 ref가 실제로 forwardRef와 함께 사용될 때만 전달되도록 타입을 정의하는 것이 안전
타입스크립트로 리액트 컴포넌트 만들기
- 공변성과 반공변성
- 일반적인 타입들은 공변성을 가지고 있어서 좁은 타입에서 넓은 타입으로 할당이 가능하다
- 하지만 제네릭 타입을 지닌 함수는 반공변성을 가진다.
- 즉,
T<B>
가T<A>
의 서브타입이 되어, 좁은 타입T<A>
의 함수를 넓은 타입T<B>
의 함수에 적용할 수 없다는 것을 의미한다. - 안전한 타입 가드를 위해서는 특수한 경우를 제외하고는 일반적으로 반공변적인 함수 타입을 설정하는 것이 권장된다.