타입스크립트란?
타입스크립트는 언어의 기본 사용법과 문법은 자바스크립트와 동일하지만, 타입을 추가적으로 선언한다는 차이가 있습니다.
타입스크립트를 사용하면 동적인 자바스크립트의 변수를 정적으로 바꿔주기 때문에 타입스크립트 컴파일 과정에서 에러를 미리 잡아줄 수 있고, 에러에 대한 메세지가 구체적으로 자세하게 나오기 때문에 최근 프론트엔드 개발자들을 중심으로 선호되고 있는 추세라고 합니다.
React와 타입스크립트
React에 타입스크립트를 적용해서 사용하는 경우에도 기존의 React와 동일한 구조를 가져갈 수 있는데, state
, props
, function
, event
등에 타입을 선언해준다는 점이 기존의 React와의 가장 큰 차이점이라고 할 수 있습니다.
State
state
는 컴포넌트 내부에서 변경되고 사용되는 변수, 즉 “상태 값”을 말하는데, 이 상태 값들은 React 훅으로 관리됩니다.
const [changeSi, setChangeSi] = useState<boolean>(false);
다음의 코드 예제들과 같이 초기값을 설정해두는 경우에는 따로 타입을 선언하지 않아도 자동으로 타입을 추정해 줍니다.
type Information = { name: string; description: string }; const [info, setInformation] = useState<Information | null>(null);
export interface IUserInfo { userid: string | undefined; username: string | undefined; } const [userInfo, setUserInfo] = useState<IUserInfo | null>(null);
type Todo = { id: number; text: string; done: boolean }; const [todos, setTodos] = useState<Todo[]>([]);
참고로 배열인 경우에는 해당 배열이 어떤 타입으로 이루어진 배열인지 추론할 수 있도록 Generics
을 명시하는 것이 좋습니다. 그리고 만약 다음과 같이 객체의 타입을 선언하는 경우에 타입이 반복 사용되는 경우라면 interface
나 type
을 이용하여 따로 생성해주는 것이 좋습니다.
/* interface */ interface loc { title: string, y: number, x: number } /* type */ type loc = { title: string, y: number, x: number } const Store:React.FC =()=>{ const [curLoc, setCurLoc] = React.useState<loc>(); return(<></>) }
Props
[props|code]는 컴포넌트 외부에서 받는 변수, 즉 “속성 값”을 말하는데, props는 컴포넌트 내부에서는 변경을 할 수 없습니다.
interface props { storeId: number, setIsWrite: React.Dispatch<React.SetStateAction<boolean>> } const ReviewForm: React.FC<props> = ({ storeId, setIsWrite }) => { /*...*/ }
props
는 컴포넌트에게 인자로 넘겨지는 값으로, React의 컴포넌트를 선언할 때 React.FC
로 타입을 선언해주고 이 뒤에 props
의 타입을 선언해주고, 받는 인자에 props
를 선언해주면 됩니다. 이렇게 선언을 해주면 외부에서 잘못된 변수를 넘겨받았을 때 에러를 잡아줄 수 있습니다.
Function
React 함수에서도 타입스크립트 사용법은 비슷합니다. 즉 들어오는 인자의 타입을 선언해주고, 추가적으로 인자 뒤에 함수의 반환 타입까지 선언해줄 수 있습니다.
const onClickFeature = (id: string) :void => { /*...*/ }
Event
React에서 타입스크립트를 적용하면서 가장 까다로운 부분이 바로 이벤트입니다. React의 요소에 어떤 타입을 선언할지 헷갈릴 수 있기 때문이죠.
const Feed :React.FC = () => { const [newNick, setNewNick] = useState({ nickName: "", valid: false, error: "" } as { nickName: string, valid: boolean, error: string }); const onChangeNick = (event: React.ChangeEvent<HTMLInputElement>) => { setNewNick({ nickName: event.target.value, valid: true, error: "사용 가능" }); } return ( <form className="col-container" onSubmit={onSubmit}> <input type="text" value={newNick.nickName} onChange={onChangeNick} /> <input type="submit" value="수정" /> </form>) } export default Feed;
onChange
의 경우 React.ChangeEvent<HTMLInputElement>
로 이벤트가 사용되고, event.target.name
, event.target.value
등으로 HTMLInputElement
속성 값을 사용할 수 있습니다.
타입 종류
자바스크립트에는 다음과 같은 원시 타입이 있습니다.
- string
- number
- boolean
- null
- undefined
- symbol
- 객체(object , array)
interface Types{ /*원시타입*/ Primitives: string, Primitives2?: number, //선언 필수 아님 /*객체*/ Object:{ a: string, b: number, } /*배열*/ Arr:{ a: string, b: number, }[] Arr2:Object[] }
interface 확장하기
interface
가 여러 곳에서 반복 사용되거나 추가적으로 사용되는 경우에는 export하거나, 확장하여 사용할 수 있습니다.
//People.tsx export interface PeopleInterface { name: string age: number } interface StudentInterface extends PeopleInterface { school: string } /* 외부 컴포넌트에서 가져오기 */ import PeopleInterface from "People.tsx"; const cmp:React.FC=()=>{ const [people, setPeople]=useState<PeopleInterface>(); }