npx create-react-app 앱이름 --template typescript
이제 TS템플릿을 기존 프로젝트에 추가하든 cra with ts로 하든 완성이 되었다면 위와 비슷한 모습을 볼 수 있다. (필자는 next로 함)
보면 .ts
와 .tsx
가 있는 것을 볼 수 있는데 .tsx
는 그 안에서 JSX문법을 사용하기 때문이다. 그럼 이제 기존 ts와 tsx의 차이점을 알아보자
사실 우리가 안해도 되지만 짚고 넘어가자
앞서 포스팅한 것처럼 TS는 JS로 한 번 컴파일을 해줘야하는데 개발서버을 확인할 때 이 작업이 필요하다. 하지만 우리가 하는건 아니고 리액트가 알아서 해준다.
단순히 이 개발 서버는 자바스크립트 코드를 받아 파일들을 하나로 묶는 작업을 수행하고 최적화 단계는 별도로 제공하였는데 지금은 이런 과정에 더해 추가적으로 타입스크립트를 자바스크립트로 컴파일하는 단계가 있다.
역시 보이지 않는 곳에서 진행되기때문에 그래서 우리가 타입스크립트를 자바스크립트로 직접 변환할 필요가 없다
TS는 TS용 컴파일러 언어로 이 프로젝트 안에 설치되어 있다. 그래서 이 프로젝트에서 TS를 사용할 수 있다.
보면 react, react-dom은 JS의 프레임워크이다. 그렇다면 우리가 TS 및 개발 툴이 제공하는 기능과 자동 완성 같은 기능을 사용하기 위해서는 TS를 JS로 변환을 해줘야하는데
이 @types
패키지가 바닐라 JS 라이브러리와 TS 프로젝트 사이에서 번역기 역할을 한다.
function Todos(props) {
...
tsconfig.json
에서 설정할 수 있다.const Todos = (props:{items:string[], children:any}) => {
@types/react
에 정의되어있는 React를 사용하면 된다.즉, FC === generics이다.
const Todos:React.FC = (props) => {
함수형 컴포넌트
로 동작한다는 걸 명확히 하는 것이다.<>
를 사용하여 가능하다.const Todos: React.FC<{ items: string[] }> = (props) => {
<>
에 들어갈 값은 데이터 타입이 아닌,그렇다면 그냥 TS가 inference하게 두면 좀 더 편리하지 않을까?
=> 우리가 추가한 props를 받아서 기본적인 props의 성질들을 사용할 수 있도록 함수를 정의하고 타입스크립트에게 이 함수를 내부적으로 어떻게 처리해야 하는지 알려줘야하기 때문에 구체적으로 정의를 해주어야한다.
<>
를 사용하여 내가 원하는 props의 필드값도 지정해줄 수 있다.단, 이렇게 되면 TS의 특징으로 해당 <Todos>
를 사용하는 컴포넌트 함수에는 빨간색 밑줄이 뜬다.
그 이유는 반드시 있어야할 items의 props이 누락되었기 때문이다.
이때 당연하게 <Todos>에 items props을 추가해도 되지만
이렇게 ?
를 사용하여 optional로 처리하여도 된다. 이때, 또 TS의 특징이 나오는데 이렇게 optional로 처리하려면 반드시 try-catch처럼 없는 경우를 또 처리해주어야한다.
그래서 컴포넌트를 잘못된 방식으로 사용하는 일, 예를 들어 컴포넌트에 필요한 props를 일부만 넘기거나 하는 일은 발생할 수 없다
정리하면 새롭게 만들 모든 컴포넌트에
React.FC
표기를 추가하면 된다.
props도 새롭게 만들어 사용한다면 이 제네릭 타입을 추가하고<>
안에 새로운 props의 타입을 정의하면 된다.
그래서 React.FC의 기본적인 props성질에<"객체">
로 구조분해한 후 내부에있는 "객체"를 더하여 하나의 완성된 props을 만드는 것이라 생각하면 편하다.
const todos = [
new Todo("Learn React"),
new Todo("Learn TypeScript")
];
return (
<>
<Todos items={todos}/>
</>
const Todos: React.FC<{ items: Todo[] }> = (props) => {
return (
<ul>
{props.items.map(item => <TodoItem key={item.id} text={item.text}/>)}
</ul>
)
}
const TodoItem:React.FC<{text:string}> = (props) => {
return(
<li>{props.text}</li>
)
}
key
부분에 빨간 밑줄이 있어야하는데 없다. 그 이유는 지금은 삭제되었지만 children
prop처럼 key
prop은 prop이 갖고있는 기본 속성중 하나이다.import {FC} from "react";
const Todos: FC<{ items: string[] }> = (props) => {
return (
<ul>
{props.items.map(item => <li key={item}>{item}</li>)}
{props.children}
</ul>
)
}
즉, 예전에는 위의 예제코드처럼 사용이 가능했지만 지금은 안 된다는 것이다.
그래서 정 사용하고 싶다면 ReactNode
객체를 가져와서 사용하면 된다고 한다.
import * as React from 'react';
type Props = {};
const Component: React.FC<Props> = ({children}) => {...}
import * as React from 'react';
type Props = {
children?: React.ReactNode
};
const Component: React.FC<Props> = ({children}) => {...}
import * as React from 'react';
type Props = {
children?: React.ReactNode
};
function Component({children}: Props): React.ReactNode {
...
}
","
면 된다.const TodoItem = <{T,}>(props:T) => {