리액트 18의 타입스크립트 타입 변경점

2022. 4. 28.

리액트 18의 타입스크립트 타입 변경점

React(리액트) 18이 얼마 전에 출시했습니다. 개발하시는 프로젝트에 이미 업데이트 했거나 조만간 업데이트 하실 계획일텐데요.

리액트와 Typescript(타입스크립트)를 같이 사용했던 프로젝트라면 반드시 수정해야 할 타입 정의의 브레이킹 체인지 몇가지 공유드립니다.

  • React.FC 타입에서 암묵적인 children 선언 제거
  • ReactFragment 타입에서 {} 제거
  • this.context는 이제 unknown 타입

어차피 검색하게 되실 겁니다. 미리 파악해두시면 좋을 것 같아요 :)

React.FC 타입에 암묵적인 children 선언 제거

약간 놀라실 분도 계실 텐데요. 자바스크립트와 리액트를 사용하시다가 타입스크립트를 나중에 적용하셨다면 대부분 검색하셨던 것 중 하나가 아마 프롭으로 children을 어떻게 선언해야 하나였을 겁니다. 검색하신 후 React.FC를 사용하는 것으로 해결하셨을 텐데요. React.FC에서 children 관련 선언이 모두 제거됩니다.

그래서 리액트를 업데이트하자마자 children을 사용했던 기존 코드는 죄다 에러와 함께 빨간불이 뜰 겁니다.

const Example: React.FC = ({ children }) => <div>{children}</div>;
// "TS2339: Property 'children' does not exist on type '{}'."

뭔가 불편할 것 같지만 children이라는 암묵적이었던 일종의 키워드는 자식 노드가 필요한지 아닌지의 의도를 명확하게 드러낼 수 없다는, 타입의 관점에서는 꽤 크리티컬한 문제를 갖고 있었습니다. 타입에 자식 노드가 꼭 필요한 컴포넌트에 자식 노드를 넣지 않았을 경우 혹은 그 반대의 경우를 타입으로 잡아내지 못한다는 단점이 있었죠.

그래서 암묵적으로 선언됐던 children을 명시적으로 컴포넌트에 맞게 선언을 하자는 취지입니다. 저는 매우 동의합니다.

이렇게 말이죠.

type Props = {
  children: React.ReactNode;
};

const Example: React.FC<Props> = ({ children }) => <div>{children}</div>;

이 컴포넌트는 자식 컴포넌트가 꼭 필요하다는 의도를 타입으로 정의했습니다.

자식 노드가 옵셔널 한 경우는 옵셔널로 선언하면 되겠죠?

type Props = {
  children?: React.ReactNode;
};

아마 기존의 React.FC안에서도 옵셔널 이었을겁니다.

매번 저렇게 선언하기 싫지만 그래도 뭔가 표준적인 방법을 원하시는 분은 PropsWithChildren를 사용할 수도 있습니다.

type Props = {
  title?: string;
};

const Example: React.FC<React.PropsWithChildren<Props>> = ({ children }) => <div>{children}</div>;

근데 왠지 코드가 더 복잡해진 느낌입니다. 제너릭이 겹칠수록 코드는 복잡해집니다. 저는 이번 변경의 의도대로 children을 그때그때 선언하는 방법이 더 좋아 보입니다.

ReactFragment 타입에서 {} 제거

children의 변경으로 생긴 추가 변경점이지만 굳이 모르셔도 되는 내용입니다. ReactFragment 타입에서 {} 즉 객체가 제거됐습니다. 일반 객체로 자식 노드를 만드는 건 이미 14버전부터 지원하지 않았지만 그동안 타입에서는 암묵적인 children 때문에 유지해왔습니다. 이번 변경으로 같이 제거됐습니다.

this.context 는 이제 unknown 타입

그동안은 any타입이었습니다. 모호하고 타입 친화적이지 않았었죠. 이제는 unknown 타입입니다. 반드시 명확한 타입으로 캐스팅해서 써야 합니다. 기존의 any로 복구하는 방법이 있지만 특별한 경우가 아니라면 모르셔도 될 것 같습니다.

♥ Support writer ♥
with kakaopay

크리에이티브 커먼즈 라이선스이 저작물은 크리에이티브 커먼즈 저작자표시-비영리-변경금지 4.0 국제 라이선스에 따라 이용할 수 있습니다.

shiren • © 2025Sungho Kim