주제: TypeScript
리액트와 웹팩, 바벨
웹팩
- 모듈 번들러입니다.
- 모듈은 하나의 파일이고, 번들은 여러 파일을 합쳐서 하나의 파일을 만들어 준 결과 파일입니다.
- 번들러는 번들을 해 줍니다.
- 리엑트 개발을 할 때 수 많은 파일이 어디에서 시작되는지 신경쓰지 않고 서로 import하며 개발을 할 수 있게 해주는 것이 웹팩입니다.
- 원래 JS에서 코드를 작성할 때 순서가 가장 중요했는데 웹팩 덕분에 상
바벨
- 컴파일러입니다.
- 컴파일러는 사람이 이해하기 쉬운 고수준 언어를 기계가 이해하기 쉬운 저수준의 언어로 바꿔주는 것을 이야기합니다.
- 바벨은 JS → JS로 컴파일해주는데 ES6를 다른 버전(ES5)로 바꿔주는 역할을 합니다. 따라서 구버전의 브라우저에서도 최신의 JS문법을 이해할 수 있도록 바꿔주는 것입니다.
- CRA, NEXT.js로 타입스크립트를 사용하면 컴파일러가 세팅되어 있기 때문에 개발자가 따로 세팅할 것은 없습니다.
- JSX도 JavaScript로 바꿔주는 역할을 하는 게 바벨입니다.
TypeScript의 특징과 장단점
특징
- 타입스크립트는 마이크로소프트가 개발한 타입이 추가된 언어입니다.
장점
- 개발 단계에서 런타임 전에 에러를 잡고 문법 오류를 찾아낼 수 있어서 개발 속도가 빨라집니다.
- 협업과 유지보수할 때도 바로 타입을 체크할 수 있으니까 코드만 가지고도 정확한 개발을 할 수 있습니다.
단점
- 타입이 엄격하기 때문에 자바스크립트의 타입 유연성 장점이 사라집니다.
- 타입 선언 때문에 오히려 생산성이 떨어질 수도 있습니다.
스크립트 언어와 컴파일 언어의 차이
- 타입스크립트는 자바스크립트로 컴파일이 필요한 컴파일 언어입니다.
- 컴파일을 하면서 미리 오류를 잡아낼 수 있습니다.
- 사용자와 직접 만나기 전에 에러를 잡아낼 수 있으니 생산성이 높아집니다.
자바스크립트에 없는 타입
any - 아무거나 타입 입력 가능 (이거 쓰면 자바스크립트랑 다른 것이 없습니다.)
void - 함수의 return이 없을 때 사용합니다.
enum - 정해진 값의 세트를 사용할 때 사용합니다. (상수 세트 값 필요할 때)
export enum AssignmentStatus {
Submitted,
Pending,
Rejected,
Passed
}
union - 여러 타입이 올 수 있을 때 사용합니다.
function formatDate(date: string | number | Date): string {
// 로직 생략
return `${year}년 ${month}월 ${day}일`
}
formatDate(20201028);
formatDate(new Date());
formatDate('20201028');
tuple
let starArr: [number, string]= [1, '1점'];
Type 별칭 (Type Alias) - 타입을 직접 만들어서 사용합니다.
type ID = number | string;
function checkInfo(info: { id: ID; pw: string }) {
}
let id: ID = "1010";
checkInfo({ id, pw: "password" });
타입추론 (Type Inference)
- 타입스크립트는 타입을 표기하지 않아도 컴파일러가 할당된 값을 보고 타입을 추축한다는 특징이 있습니다. (일반 정적타입언어와 다른 점입니다.)
- 정말 타입이 필요가 없을 때 타입 쓰는 것을 생략하는 경우도 있습니다.
let starArr = [1, 2, 3];
starArr.push('4점'); // 에러: Argument of type 'string' is not assignable to parameter of type 'number'.
인터페이스 (Interface)
- 객체의 타입을 정의할 때 많이 쓰입니다.
객체 타입 정의
- 바로 타입을 정의하는 방법
function getInfo(restaurant: **{ name: string }**) {
console.log(restaurant.name);
}
- 인터페이스 ( 2개 이상)
interface Restaurant {
name: string;
star: 5;
}
function getInfo(restaurant: Restaurant) {
console.log(restaurant.name);
}
const chroad3 = {
name: "취향로3가",
star: 5
};
getInfo(chroad3);
- 아래와 같이 예정되지 않은 프로퍼티를 추가하면 에러가 납니다.
interface Restaurant {
name: string;
star: number;
}
const chroad3: Restaurant = {
name: "취향로3가",
star: 5,
address: "을지로3가",
};
- 그런데 타입 추론을 통해서 아래 코드는 에러가 안 납니다.
interface Restaurant {
name: string;
star: number;
}
const chroad3Value = {
name: "취향로3가",
star: 5,
address: "을지로3가",
};
const chroad3: Restaurant = chroad3Value;
다양한 프로퍼티 타입
- 객체의 프로퍼티 타입을 다양하게 사용할 수 있습니다.
인터페이스 확장
- extends 키워드를 사용해서 인터페이스를 확장할 수 있습니다.
interface BasicInfo {
name: string;
star: number;
}
interface DetailInfo extends BasicInfo {
address: string;
phone: string;
position: number[];
}
교차 타입(Intersection Types) 활용
- &기호를 사용해서 기종 정의했던 인터페이스를 합쳐서 새로운 타입을 만드는 것입니다.
- 이때는 interface를 쓸 수 없습니다.
- type으로 만들어야 합니다.
interface BasicInfo {
name: string;
star: number;
}
interface DetailInfo {
position: number[];
}
**type** Info = BasicInfo & DetailInfo;
- Info타입은 position, name, star 전부 다 필요합니다.
타입호환성 (Type Compatibility)
interface Restaurant {
name: string;
star: number;
}
let **chroad3**: Restaurant; // chroad3 변수 선언
let chroad3withAddress = { // chroad3withAddress 변수 선언하고 초기화
name: "십분의일",
star: 5,
address: "을지로3가",
};
chroad3 = chroad3withAddress;
- 위 코드는 에러가 나지 않습니다. 왜냐하면 chroad3withAddress가 타입을 초기화했기 때문입니다.
- 이렇게 호환되기 위한 조건은 오른쪽에 있는 타입이 왼쪽을 포함해야 합니다.
function getStar(score: number | string, scoreNum: number) {
const v1: number = score;
const v2: number | string = scoreNum;
}
- v1은 score에 string을 넣은 것이 오면 타입이 string으로 되어서 에러가 날 것입니다.
제네릭 (Generic)
- <>을 사용하면서 유동적으로 타입이 정의됩니다.
- 고정된 타입이 아니고 내가 원하는 타입을 자유롭게 지정해서 사용하고 싶을 때 사용합니다.
function makeArr<T>(el: T): T[] {
return [el];
}
makeArr<number>(1); // 1
makeArr<string>("1점"); // 2
makeArr<boolean>(true); // 3
- <>에 number를 넣으면 T는 넘버가 됩니다.
- <>에 string을 넣으면 T는 string이 됩니다.
- <>boolean을 넣으면 T는 boolean이 됩니다.
makeArr(1);
makeArr("1점");
makeArr(true);
- 위처럼 넣어도 되지만 타입을 넣는 연습을 합시다.
- 유지 보수가 힘들어질 것입니다.
리엑트를 위한 타입스크립트
Type보다는 Interface!
공식 문서에서 Inteface를 쓰라고 나와 있습니다. type을 써도 되지만 공식 문서에 따르는 것이 좋을 것 같습니다.
Type과 Interface 차이
- type은 정의를 볼 때 모든 프로퍼티가 다 나옵니다. (vscode에서)
- inteface는 inteface이름만 간결하게 나옵니다.
리엑트의 FC 타입 사용
- React.FC를 쓰거나
- input, output 타입을 정하거나 하면 됩니다.
**interface StarsProps {** // prop 타입 정의
star: number;
}
const Stars: React.**FC<StarsProps>** = ({ star }) => { // 2
// 로직
return (
<div>
{makeStars(star)}
</div>
)
}
Hooks
- useState
- 제네릭으로 타입을 넣습니다.
const [like, setLike] = useState<boolean | null>(null);
//유니온으로 초기 null 값도 넣을 수 있습니다.
useRef
- 코드의 명확성을 위해 타입을 정의하고 싶은 경우는 ref의 태그에 맞는 제네릭을 넘겨주면 됩니다.
const reviewRef = useRef<HTMLDivElement>(null);
- HTMLAnchorElement, HTMLButtonElement, HTMLTableElement 등이 있습니다.
이벤트 핸들러
const updateValue = (e: React.ChangeEvent<HTMLInputElement>) => { // 1
setEmail(e.target.value);
};
- 타입 이름은 ‘이벤트타입Event’로 쓰면 됩니다. (ChangeEvent, FormEvent, TouchEvent, FocusEvent, KeyboardEvent, MouseEvent, DragEvent)
기타
JSX.Element
- 변수에 JSX를 할당해서 값을 사용하는 경우 아래와 같이 선언합니다.
const WarningText: JSX.Element = <p>다시 확인해주세요.</p>
전역 변수
- window에 외부 라이브러리 변수를 추가하려면 라이브러리에서 사용하는 전역 변수명을 추가하면 됩니다.
declare global {
interface Window {
kakao: any;
}
}
- 카카오 지도, 로그인 라이브러리 추가할 때 window.kakao로 접근하면 됩니다.
♧ 이 내용은 원티드, 위코드 프리온보딩 코스 강의를 들으면서 정리한 내용입니다.
Comments