이제는 타입스크립트를 사용하지 않은 자바스크립트 코드를 찾기 힘들 만큼, 타입스크립트는 선택보다는 필수에 가까워지고 있는 느낌이다. 타입스크립트가 2014년 출시되었지만 2021년 기준 어느새 4위를 기록하고 있는 언어가 될 수 있게 한 TS만의 매력은 무엇일까?
타입스크립트의 특징
TypeScript is JavaScript with syntax for types.
자바스크립트는 동적 언어이다. 따라서 JS는 런타임에만 타입 체크가 가능하다. 즉, 코드를 실행해서 에러가 났을 때 비로소 타입 에러를 확인할 수 있는 것이다. 타입스크립트는 JS의 문법에 타입을 추가해 이런 위험성을 줄일 수 있도록 한다.
타입 체크를 정적으로 빌드(트랜스파일) 타임에 할 수 있게 해주기 때문에 훨씬 안전하고 버그를 예방할 수 있도록 코드 작성을 도와준다.
TS는 JS의 슈퍼셋으로, 기존 JS에서 한계가 있었던 함수의 반환 타입, 배열, enum 등 타입 관련 작업들을 용이하게 처리할 수 있도록 해준다. 다만 JS의 슈퍼셋이므로, JS에서 불가능한 일은 TS에서도 불가하다.
결국 TS의 궁극적인 목표는 JS로 변환되어 JS 런타임 환경에서 실행되는 것이 목표이기 때문이다.
리액트 프로젝트에서의 타입스크립트 활용 팁
1. any -> unknown
- any는 어떤 값도 할당 가능(top type)하고 사용 가능하다. 즉, TS의 모든 장점을 완전히 포기한 셈이다.
- unknown은 어떤 값도 할당할 수 있지만(top type) 바로 사용 불가하다. 적절히 타입 범위를 지정해주어야 한다(type narrowing). 아직 알 수 없어(unknown) 사용이 불가하기 때문이다.
top type vs bottom type
- top type : 어떤 값도 할당 가능
- bottom type: never이 이에 해당. 어떤 값도 들어올 수 없음.
2. 타입 가드 활용하기
앞서 설명한 것과 같이, TS를 사용할 것이라면 최대한 타입을 좁은 범위로 좁혀주는 것이 좋다. 이때 사용하면 좋은 것이 조건문&타입 가드의 조합이다. 변수나 함수를 볼다 명확하게 사용 가능하다.
3. instanceof vs typeof
- instanceof : 지정한 인스턴스가 특정 클래스의 인스턴스인지 확인
- typeof : 특정 요소에 대한 자료형을 확인
4. in
property in object 형식으로 사용하며, 특정 객체에 해당 키가 존재하는지 확인하기 위해 사용한다.
5. 제네릭
함수/클래스 내부에서 다양한 타입에 대응 가능하게 도와주는 문법이다.
비슷한 작업을 하는데 타입만 다른 컴포넌트를 하나의 제네릭 컴포넌트로 선언하면 코드를 간결하게 작성 가능하다.
리액트에서는 대표적으로 useState
에 제네릭을 사용할 수 있다. 초기값 설정을 하지 않으면 undefined로 추론되지만, 제네릭을 사용하면 이를 예방 가능하다. 보통 제네릭을 알파벳(T, U 등)으로 표현하지만, 의미를 명시해주는 네이밍이 더 좋다.
function multipleGeneric‹First, Last>(al: First, a2: Last): \[First, Last\] {
return [a1, a2]
}
const [a, b] = multipleGeneric<string, boolean>('true', true)
a // string
b // boolean
6. 인덱스 시그니처
객체의 키를 정의하는 방식을 의미한다. 즉, 키에 원하는 타입을 부여 가능하다.
type Hello = {
// key에 string이라는 타입을 지정했다
[key: string]: string
}
왜 키에 타입을 선언하는 것이 좋을까?
객체의 키 범위가 너무 포괄적이면 존재하지 않는 키로 접근해서 undefined를 반환할 가능성이 있어 최대한 객체 타입과 키는 적절히 범위를 지정해주어야 한다.
객체에 Record<Key, Value>
를 통해 객체 타입에 원하는 키와 값을 넣을 수 있다.
이를 활용해 TS에서 지정된 Object.keys
의 반환 타입 string[]
을 대신해 개발자가 지정한 타입으로 강제할 수 있다.
// 타입가드 함수
function keysOf<T extends Object>(obj: T): Array<keyof T> {
return Array.from(Object.keys(obj)) as Array<keyof T›
}
keysOf (hello).map((key) ›= {
const value = hello \[key\]
return value
})
그렇다면 왜 TS에서 Object.keys
의 반환 타입은 string[]
으로 지정되어 있을까?
JS의 덕타이핑(duck typing)으로 객체를 비교하는 특징을 TS 또한 구현하고 있기 때문이다.
덕 타이핑은 객체의 타입이 특정 객체에 필요한 변수, 메서드만 가지고 있으면 해당 타입에 속하는 것으로 인정해준다는 의미이다.
즉, 값의 형태에 초점을 맞춰 타입 검사를 한다.
따라서 TS에서 Object.keys
는 JS의 모든 키가 들어올 수 있는 객체의 키에 포괄적으로나마 대응하기 위해 string[]
타입으로 지정하고 있다.
Reference
- 저자
- 김용찬
- 출판
- 위키북스
- 출판일
- 2023.11.07
'WEB > React' 카테고리의 다른 글
메모이제이션과 useMemo는 적극 사용할수록 좋을까? (0) | 2024.03.12 |
---|---|
리액트의 핵심 요소들 (0) | 2024.03.03 |
[리액트 딥다이브] useImperativeHandle (1) | 2024.02.25 |
[리액트 딥다이브] useState (0) | 2024.02.18 |
[리액트 딥다이브] 1.4 클로저 (0) | 2024.02.18 |