TypeScript를 배우는 도중, 함수를 const App = () => {}
또는 function App () {}
를 사용해서 선언하는 것을 보고 무슨 차이인가, 뭐가 더 나은가에 대한 궁금증으로 인해 찾아보게 되었다.
대부분의 글들이 React.FC는 잘 안 쓴다, 지양하는 것이 좋다고 하는데, 그 이유는 아래와 같다.
암시적으로 children을 가지는 건 지금은 사라졌다고 하니, 제네릭을 지원하지 않는 부분에 대해 포스팅하려고 한다.
React.FC는 제네릭을 지원하지 않는다.
기존에는 아래 코드처럼 정적으로 타입을 지정해줬다.
function add(n1: number, n2: number): number {
return n1 + n2;
}
하지만 간혹 파라미터로 어떤 타입이 들어올지 모를 때가 있는데 그럴 경우 제네릭을 사용한다.
제네릭은 아래의 코드처럼, 타입을 함수의 파라미터처럼 사용하는 것이다.
function getPost<T>(Post: T): T {
return Post;
}
getPost<string>('hi'); // function getPost<string>(Post: string): string
getPost<number>(10); // function getPost<number>(Post: number): number
getPost<boolean>(true); // function getPost<boolean>(Post: boolean): boolean
// <>부분 생략 가능
getPost('hi');
getPost(10);
getPost(true);
파라미터의 타입에 따라 함수의 타입이 달라진다.
근데 React.FC를 사용하면 아래처럼 제네릭을 사용할 수 없게 된다.
import { FC } from "react";
interface myProps<T> {
name: T;
}
// 사용 불가. (<T> 없음)
const TodoForm: FC<myProps> = ({ name }) => { // 'myProps<T>` 제네릭 형식에 1 형식 인수가 필요합니다.
return <div>{name}</div>;
};
// 사용 불가. (<T> 넣지 못함)
const TodoForm: FC<myProps<T>> = ({ name }: T) => { // 'T' 이름을 찾을 수 없습니다.
return <div>{name}</div>;
};
아래처럼 선언식을 이용하면 제네릭을 사용할 수 있다.
import { FC } from "react";
interface myProps<T> {
name: T;
}
// 사용 불가능.
function TodoForm<T>({ name }: myProps<T>) {
return <div>{name}</div>; // 'T' 형식은 'ReactNode' 형식에 할당할 수 없습니다. 'T' 형식은 'ReactPotal' 형식에 할당할 수 없습니다.
}
// 사용 가능.
function TodoForm<T extends ReactNode>({ name }: myProps<T>) {
return <div>{name}</div>; // ReactNode 또는 ReactPotal 필요
}