https://kentcdodds.com/blog/how-to-write-a-react-component-in-typescript
위 글을 참고했습니다.
Calculator라는 컴포넌트가 있습니다.
이 컴포넌트는 타입스크립트 적용이 안되어 있습니다.
const operations = {
'+': (left, right) => left + right,
'-': (left, right) => left - right,
'*': (left, right) => left * right,
'/': (left, right) => left / right,
}
function Calculator({left, operator, right}) {
const result = operations[operator](left, right)
return (
<div>
<code>
{left} {operator} {right} = <output>{result}</output>
</code>
</div>
)
}
const examples = (
<>
<Calculator left={1} operator="+" right={2} />
<Calculator left={1} operator="-" right={2} />
<Calculator left={1} operator="*" right={2} />
<Calculator left={1} operator="/" right={2} />
</>
)
잘 동작하겠지만 Calculator 컴포넌트에 타입을 적용해도 좋을 것 같습니다.
left, operator, right는 정해진 데이터만 받아야 하니까요.
따라서 아래와 같은 type을 만들었습니다.
type CalculatorProps = {
left: number
operator: '+' | '-' | '*' | '/'
right: number
}
위 타입을 React.FC와 제네릭을 이용해서 Calculator 컴포넌트에 적용해봅니다.
const Calculator: React.FC<CalculatorProps> = ({left, right, operator}) => {
// implementation clipped for brevity
}
React.FC
꽤나 많은 사람들이 FC type을 리액트 컴포넌트에 적용하고 있습니다.
하지만 FC type은 몇가지 문제점이 있습니다.
- FC type은 children을 허용합니다. 따라서 Caculator는 children을 임의적으로 사용하는 것 처럼 됩니다. 타입을 명확히 하기 위해 타입스크립트를 이용하는 것인데, 의도치 않은 props가 컴포넌트에 들어가는 것 처럼 보이게 됩니다.
컴파일 시 아래 코드와 같이 될 것입니다.
<Calculator left={1} operator="+" right={2}>Children?????</Calculator>
- FC<CalculatorProps>에서 이미 제네릭을 사용하고 있으므로, 추가적인 제네릭을 활용할 수 없습니다.
- 표현식: React.FC<CalculatorProps>와 같이 함수 표현형에 타입을 지정해주어야 하므로, 함수 선언식을 이용할 수 없습니다.
대안
의도치 않은 children을 허용한다는 것이 React.FC의 가장 큰 단점일 것입니다.
따라서 아래와 같이 타입을 지정하는 것이 바람직합니다.
function Calculator({left, operator, right}: CalculatorProps) {
// implementation clipped for brevity
}
리액트18 버전에서는 React.FC<제네릭>에 children 타입이 자동적으로 추가되는 것이 빠졌고,
대신에 PropsWithChildren 타입이 새로 생겼습니다.
type PropsWithChildren<P = unknown> = P & { children?: ReactNode | undefined };
앞으로는 취향껏 취사선택해서 사용하면 되겠습니다.
(그래도 타입을 직접 지정해줘야 한다는 타입스크립트의 이념 상 직접 children도 직접 지정해주는 것이 맞지 않나 라는 생각이 있습니다.)
'Typescript' 카테고리의 다른 글
유틸리티 타입 (Partial, Required, Record) (0) | 2023.10.27 |
---|---|
keyof typeof typesomething (0) | 2023.09.05 |
catch문의 error 타입이 any 또는 unknown여야 하는 이유 (0) | 2023.08.09 |
함수 표현식에 타입 적용하기 (0) | 2023.07.31 |
타입 단언과 타입 선언 사용 시기 (0) | 2023.07.27 |