[내배캠] React에서 TypeScript 시작하기
타입스크립트의 기초
타입스크립트란?
타입스크립트란 자바스크립트에 타입 시스템을 추가한 것.
타입 시스템이란, 프로그램이 실행되기 전(컴파일 타임)에 모든 변수와 표현식의 타입을 확인하고 고정하는 방식이다.
자바스크립트의 유연성을 막아주고 엄격하게 검사하기 때문에 프로그램의 에러를 상당 부분 예방해줄 수 있다는 장점이 있다.
type Wonyoung = '장원영';
const userName: Wonyoung = '안유진'; // 에러
타입스크립트를 사용하는 이유
1. 에러를 코드 작성 시에 미리 발견할 수 있다.
자바스크립트의 경우 타입이 잘못 되더라도 일단 코드는 실행되기 때문에 프로젝트가 커지면 커질 수록 디버깅이 불가능에 가까워질 수 있다.
2. 더 빠른 실행 가능
자바스크립트에서 변수나 표현식의 타입은 코드가 실행되는 시점에 정해진다. 그런데 타입스크립트는 미리 정하고 시작하기 때문에 컴파일러에 따라 다르지만 정적 언어의 특성인, 실행 속도가 빠르다는 장점이 있을 수도 있다.
타입스크립트는 다른 언어인가?
타입스크립트는 100% 자바스크립트 언어이다. 다만 코드 에디터에서 변수나 표현식에 type만 지정해주는 것이다.
웹 브라우저는 타입스크립트를 해석하지 못한다. 자바스크립트만 해석할 수 있다. 따라서 타입스크립트는 파일을 웹 브라우저로 보낼 때 자바스크립트로 변환해서 보낸다.
즉 타입스크립트에서 타입을 빼더라도 에러가 나는 것은 아니다.
하지만 타입을 지정하는 것만으로도 엄청난 장점이 있기 때문에 사용한다.
타입스크립트 리액트 프로젝트 셋업
yarn create vite@latest
패키지 설치 후 TypeScript 또는 TypeScript + SWC(개선된 언어)를 선택하면 타입스크립트용 리액트 프로젝트가 셋업된다.
기존 자바스크립트 프로젝트에서는 없던 파일이 생긴다. tsconfig.app.json, tsconfig.json 파일이 생긴다.
그리고 package.json에서 devDependencies에 typescript가 설치되어 있다.
특히 tsconfig.json에 들어가면 여러 줄로 작성된 옵션들이 보인다.
어떤 옵션들이 있는지 정도만 참고하고, 깊게는 몰라도 프로젝트를 진행하는 데 큰 어려움이 없다.
tsconfig 옵션은 아래에서 확인할 수 있다.
기존 자바스크립트 프로젝트에서 타입스크립트로 전환하는 방법
package.json에 의존성에 typescript 줄을 그대로 복사해서 붙여 넣은 후, tsconfig.json 파일을 만들고 내용을 복붙해주면 된다.
기초 문법
타입의 종류
엄청 많다. 그런데 실제로 많이 사용하는 것은 아래와 같다.
원시 타입(내장 타입, built-in type)
- number
- string
- boolean
- object
- array
- function
- void : return값이 없는 함수의 타입.
- undefined
- any : 타입 검사를 무시함. 치트키 같은 개념. 가급적 사용 지양.
- null
커스텀 타입(type alias, interface)
type alias (타입 별칭)
// type alias(타입 별칭)
type UserName = string;
const userName: UserName = '장원영';
// type alias 객체 타입
type MyObj = {
name: string,
age: number
}
const myObj: MyObj = {
name: '장원영'
age: 21
}
interface
// interface
interface ExampleInterface {
example : string;
}
type alias와 interface는 얼핏 비슷해보이는데, 어떤 것을 사용해야 하는 지는 아직도 논란이다. 그런 타입스크립트 공식문서에서는 둘의 성격이 매우 비슷하니 취향에 맞게 사용해도 된다고 말하고 있다.
그러나 꼭 하나만 선택해서 혼란을 줄이고자 한다면 type을 사용하는 것이 초보자 입장에서 더 직관적일 것이다.
타입 추론과 타입 명시
타입 추론
const [count, setCount] = useState(0);
setCount(''); // 에러
위 상태를 보면 useState의 initialState로 타입을 지정하지 않았지만 0이라는 초기값을 할당해줌으로써 타입스크립트 파일에서는 count라는 상태의 타입은 number라고 추론해준다. 타입을 명시하지 않았을 때 타입이 추론이 잘 되었는지 확인해보려면 에디터에서 해당 변수나 표현식에 마우스를 hover 해보면 된다.
그리고 function App () {}과 같은 함수형 컴포넌트에는 어떤 타입을 지정해주어야 하는지 잘 모를 수 있는데, 자동으로 추론해주기 때문에 잘 모르겠는데 명시를 해주고 싶으면 마우스를 hover해서 추론된 것을 그대로 명시해주면 된다.
타입 명시
그런데 중요한 것은 타입스크립트 파일에서 변수나 표현식의 타입을 자동으로 추론해준다고 하더라도, 명시해주는 것을 습관화하면 좋다. 타입을 이렇게 명시해주는 것을 타입 어노테이션이라 한다.
// Type annortation
const subtract = (a: number, b: number) :number => {
return a - b;
}
구조적 타입
타입스크립트는 구조적으로 같으면 같은 타입으로 간주한다.
덕 타이핑이라고도 한다.
제네릭
타입을 클래스나 함수에서 파라미터처럼 사용하는 것.
function sum(a:number, b:number): number {
return a + b;
}
sum(1, 2); // 3
// Generic
type Generic<T> = {
name: T
}
type Example = Generic<string>;
위 제네릭 예시에서 <string>으로 타입을 명시하면 마치 이것은 Generic이라는 함수의 파라미터처럼 작동해서 <T> 자리에 전달된다. 따라서 Generic이라는 객체의 name 프로퍼티의 값은 string 타입으로 지정된다.
리액트에서 사용하기
Todo List에서 실습하기
타입 지정하기
// App.jsx
type Todo = {
id: string;
title: string;
description: string;
};
const mockTodo: Todo = {
id: crypto.randomUUID(),
title: '할 일 제목',
description: '할 일 내용'
};
function App () {
return(...)
};
이 예시는 카드 하나를 만든 거고 리스트를 만들려면 배열을 사용해야 한다.
리스트 만들기(배열)
// App.jsx
type Todo = {
id: string;
title: string;
description: string;
};
type TodoList = Todo[]; // TodoList라는 배열 타입 지정
const mockTodo: Todo = {
id: crypto.randomUUID(),
title: '할 일 제목',
description: '할 일 내용'
};
const todoList: TodoList = [mockTodo]; // 배열 만들기
function App () {
return(...)
};
상태의 초기값 지정하기
type TodoList = Todo[]; // TodoList라는 배열 타입 지정
// 타입 추론 : 초기값을 빈 배열로 두어서 빈 배열로 됨.
const [todoList, setTodoList] = useState([]);
// 타입 지정(제네릭)
const [todoList, setTodoList] = useState<TodoList>(todoList);
배열로 렌더링 하기
return (
<>
{todoList.map(( {id, title, content} )=>(
<div key={id}>
<h1>{title}</h1>
<p>{content}<p>
</div>
))}
</>
)
이벤트 핸들러 함수의 매개 변수 타입 지정하기
const onTitleChange = (e) => {
setTitle(e.target.value);
} // 에러
매개 변수 e의 타입을 지정해주지 않아서 에러가 발생한다.
만약 event의 타입이 무엇인지 모르겠다면 입력 필드에 onChange에 연결해보고 마우스를 hover 해보면 타입의 종류를 알려준다. 그것을 그대로 복붙해주면 된다.
const onTitleChange = (e: React.ChangeEvent) => {
setTitle(e.target.value);
} // 에러
그런데 setTitle의 매개 변수인 e.target.value 또한 타입을 지정해주어야 하기 때문에 또 에러가 뜬다.
'Programing > TypeScript' 카테고리의 다른 글
[코딩애플] 함수와 methods에 type alias 지정하기 (0) | 2024.06.25 |
---|---|
[코딩애플] literal types, as const (0) | 2024.06.25 |
[코딩애플] Type Alias / readonly (0) | 2024.06.25 |
[코딩애플] 타입 확정하는 Narrowing / Assertion (0) | 2024.06.25 |
[코딩애플] 함수에 타입 지정하는 법, void 타입 (0) | 2024.06.24 |
댓글