타입스크립트란?
타입스크립트는 언어의 기본 사용법과 문법은 자바스크립트와 동일하지만, 타입을 추가적으로 선언한다는 차이가 있습니다.
타입스크립트를 사용하면 동적인 자바스크립트의 변수를 정적으로 바꿔주기 때문에 타입스크립트 컴파일 과정에서 에러를 미리 잡아줄 수 있고, 에러에 대한 메세지가 구체적으로 자세하게 나오기 때문에 최근 프론트엔드 개발자들을 중심으로 선호되고 있는 추세라고 합니다.
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>();
}