초보 개발자의 성장 일기
[TypeScript] 래퍼 컴포넌트를 작성할 때 타입 오류 본문
사이즈 별로 div 컴포넌트를 만들었고, "medium"을 props로 넣어주면 설정해준 width, height가 나오는데 props를 지정하면 컴포넌트에 에러가 났다.
'{ children: Element; size: string; }' 형식은 'IntrinsicAttributes & Size' 형식에 할당할 수 없습니다.
'IntrinsicAttributes & { size: Size; }' 형식에 'children' 속성이 없습니다.
return (
<>
<Container size="medium"> // 에러
<S.User>
<div>
<img src={image} />
</div>
</S.User>
</Container>
</>
);
}
Container에는 아래와 같이 컴포넌트를 만들었다.
import { StyledContainer } from '@/src/components/Home/Container/Container.styles';
type Size = 'small' | 'medium' | 'large';
function Container(size: Size) {
return <StyledContainer size={size}></StyledContainer>;
}
export default Container;
IntrinsicAttributes의 뜻을 검색해보니 '본질적인 속성'이었다.
props로 넘겨준 size를 컴포넌트 파일에서 받지 못하는건가 싶어서 찾아보다가,
ReactNode를 작성하면 에러가 사라진다는 글을 보고 children에 React.ReactNode를 작성해주었더니 에러가 사라졌다.
import { StyledContainer } from '@/src/components/Home/Container/Container.styles';
type Size = 'small' | 'medium' | 'large';
type ContainerProps = {
size: Size;
children: React.ReactNode;
};
function Container({ size }: ContainerProps): JSX.Element {
return <StyledContainer size={size}></StyledContainer>;
}
export default Container;
자식 요소를 감싸는 래퍼 컴포넌트를 작성할 때 자식 요소인 children 속성의 타입을 명시해야 한다고 한다.
ReactNode외에도 ReactChild, ReactElement가 있었다.
이 세가지 차이에 대해 궁금해져서 더 자세히 공부했다.
◾️ React.ReactNode
ReactNode 타입은 jsx 내에서 사용할 수 있는 모든 요소의 타입이며 string, null, undefined 등을 포함하는 가장 넓은 범위를 갖는 타입이다.
type ReactNode = ReactChild | ReactFragment | ReactPortal | boolean | null | undefined;
◾️ React.ReactChild
type ReactChild = ReactElement | ReactText;
ReactElement타입과ReactText (string, number)를 포함한다.
◾️ React.ReactElement
interface ReactElement<P = any, T extends string | JSXElementConstructor<any> = string | JSXElementConstructor<any>> {
type: T;
props: P;
key: Key | null;
}
ReactElement 는 createElement 함수를 통해 생성된 객체의 타입이다.
ReactNode 와는 달리 원시 타입을 허용하지 않고 완성된 객체(컴포넌트) 요소만을 허용한다.
자식 요소로 하나의 "컴포넌트" 를 받는 것을 강제해야 하는 상황에 사용한다.
ReactNode 와 ReactElement 의 큰 차이점은 javascript 의 원시타입의 허용 유무의 차이이다.
컴포넌트를 자식으로 받아서 사용하려고 하는 경우에는 ReactElement를 사용하는 것이 좋다.
타입별 허용 범위 : ReactNode > ReactChild > ReactElement
import { StyledContainer } from '@/src/components/Home/Container/Container.styles';
type Size = 'small' | 'medium' | 'large' | 'long';
type ContainerProps = {
size: Size;
children: React.ReactElement;
};
function Container({ size, children }: ContainerProps) {
return <StyledContainer size={size}>{children}</StyledContainer>;
}
export default Container;
자식 컴포넌트들도 타입을 지정해줬고, props로 자식 컴포넌트를 넘겨서 지정해주었더니 정상적으로 잘 작동한다.
'Development > TypeScript' 카테고리의 다른 글
[TypeScript] HTMLInputElement에 number 적용하는 방법 (0) | 2024.04.17 |
---|---|
[TypeScript] Vite 절대 경로를 설정하는 방법 (0) | 2024.03.12 |
[TypeScript] 타입 대입시 주의점 (0) | 2024.02.23 |
[TypeScript] 타입 가드로 매개변수의 타입을 구분하여 메서드 적용하기 (0) | 2024.02.23 |
타입 추론 (0) | 2023.12.10 |