[8장] 타입스크립트로 마이그레이션하기이펙티브 타입스크립트 8장을 정리한 내용입니다.작성일 2024.02.14페이지가 생성된 시간 2024.11.16 01:32:32
8장 타입스크립트로 마이그레이션하기
한꺼번에 많은 코드를 타입스크립트로 전환할 수 없기 때문에, 대규모 프로젝트를 마이그레이션할 때는 점진적으로 전환해야 합니다.
목표
- 마이그레이션을 하는 방법을 안다
- 점진적 마이그레이션 학습
- 마이그레이션 진행 상황을 수치화하는 방법을 안다
아이템58
모던 자바스크립트로 작성하기
우선 옛날 버전의 자바스크립트를 최신 버전의 자바스크립트로 바꾸기
옛날 버전의 자바스크립트를 최신 버전으로 바꾸는 것은 타입스크립트로 전환하는 과정의 일부로 볼 수 있다.
ECMAScript 모듈 사용하기
import
, export
ES 모듈은 타입스크립트에서도 잘 동작하며, 모듈 단위로 전환할 수 있어 점진적 마이그레이션이 원활해진다.
프로토타입 대신 클래스 사용하기
클래스로 구현한 객체가 프로토타입보다 간결하고 직관적이다.
편집기에서 프로토타입 객체를 클래스 객체로 변환할 수 있다.
var 대신 let / const 사용하기
자바스크립트의 var는 스코프 규칙에 문제가 있다.
for(;;) 대신 for-of 또는 배열 메서드 사용하기
for-of 루프는 코드가 짧고 인덱스 변수를 사용하지 않아 실수를 줄일 수 있다.
인덱스 변수가 필요한 경우에는 forEach메서드를 사용하면 된다.
for-in 문법은 몇 가지 문제점이 있어 사용하지 않는 것이 좋다. (아이템 16에 있다?)
함수 표현식보다 화살표 함수 사용하기
화살표 함수를 사용하면 상위 스코프의 this를 유지할 수 있다.
인라인 또는 콜백에서는 화살표 함수를 쓰자. 더 직관적이고 코드도 간결하다.
컴파일러 옵션에 noImplicitThis 를 설정하면 타입스크립트가 this 바인딩 관련된 오류를 표시해준다.
단축 객체 표현과 구조 분해 할당 사용하기
단축 객체 표현은 가독성이 좋고 실수가 적다
const x = 1;
const y = 2;
const z = 3;
const pt = { x, y, z };
구조 분해 할당을 사용하면 문법이 간결해지고 변수를 사용할 때 실수를 줄일 수 있으므로 적극적으로 사용하자
함수 매개변수 기본값 사용하기
자바스크립트 함수의 모든 매개변수는 선택적이며 지정하지 않으면 undefined로 간주된다.
매개변수에 기본값을 지정하면 코드가 간결해지고 선택적 매개변수라는 것을 명확히 나타내는 효과를 줄 수 있다.
기본값을 기반으로 타입 추론이 돼서 타입 구문을 쓰지 않아도 된다.
저수준 Promise나 콜백 대신 async / await 사용하기
async / await 사용하면 코드가 간결해지고 비동기 코드에 타입 정보가 전달되어 타입 추론을 가능하게 한다.
연관 배열에 객체 대신 Map과 Set 사용하기
인덱스 시그니처의 문제점
function countWords(text: string) {
const counts: { [word: string]: number } = {};
for (const word of text.split(/[\s,.]+/)) {
counts[word] = 1 + (counts[word] || 0);
}
return counts;
}
console.log(countWords('Objects have a constructor'));
constructor의 값은 undefined가 아니라 Object.prototype에 있는 생성자함수이다.
그래서 의도와 다른 동작을 하게 됨
이런 문제를 방지하기 위해 Map을 사용할 수 있다.
타입스크립트에 use strict 넣지 않기
타입스크립트에서 수행되는 안전성 검사가 엄격 모드보다 훨씬 더 엄격하기 때문에 use strict
는 무의미하다.
실제로 타입스크립트가 생성하는 자바스크립트 코드에 use strict
가 추가된다.
요약
- 모던 자바스크립트를 사용하자
- 타입스크립트에서는 언어서비스를 통해 모던 자바스크립트 기능을 쉽게 배울 수 있다
use strict
는 코드에서 제거하자- TC39의 깃헙 저장소와 타입스크립트 릴리스 노트를 통해 최신 기능을 확인하자
아이템59
타입스크립트 도입 전에 @ts-check와 JSDoc으로 시험해보기
@ts-check는 느슨한 타입 체크를 해준다.
@ts-check 예시
-
선언되지 않은 전역 변수
// types.d.ts interface UserData { firstName: string; lastName: string; } declare let user: UserData; export default {}; // @ts-check /// <reference path="./types.d.ts" /> console.log(user.firstName);
types.d.ts 와 같은 파일을 만들어서 해결. 선언 파일을 찾지 못하는 경우 트리플 슬래시 임포트 사용
-
알 수 없는 라이브러리
@types 설치하자
-
DOM 문제
// @ts-check const ageEl = /** @type {HTMLInputElement} */ document.getElementById('age'); ageEl.value = '12'; // OK
-
부정확한 JSDoc
JSDoc 이 많이 작성된 프로젝트에 @ts-check 지시자를 추가하면 오류가 날 수 있다.
당황하지 말고 하나씩 수정하자
@ts-check 지시자를 통해 기존 코드에 타입체커를 시험해볼 수 있고 초기 오류를 빠르게 잡을 수 있다.
요약
- @ts-check를 파일 상단에 추가하면 자바스크립트에서도 타입 체커를 쓸 수 있다
- JSDoc을 잘 활용하면 자바스크립트에서도 타입 단언과 추론을 할 수 있다
- JSDoc은 마이그레이션 중간 단계이므로 너무 공들이지는 말자
아이템60
allowJs로 타입스크립트와 자바스크립트 같이 사용하기
요약
- 점진적 마이그레이션을 위해 자바스크립트와 타입스크립트를 동시에 사용할 수 있게 allowJs 컴파일러 옵션을 사용하자
- 번들러에 타입스크립트가 통합되어 있거나, 플러그인 방식으로 통합이 가능하다면 allowJs를 간단히 적용할 수 있다
- 대규모 마이그레이션 작업을 시작하기 전, 테스트와 빌드 체인에 타입스크립트를 적용하자
아이템61
의존성 관계에 따라 모듈 단위로 전환하기
점진적 마이그레이션은 모듈 단위로 진행하게 된다.
한 모듈에 타입 정보를 추가하면, 해당 모듈이 의존하는 모듈에서 비롯되는 타입 오류가 발생한다.
따라서 다른 모듈에 의존하지 않는 최하단 모듈부터 작업을 시작해야 한다.
(서드파티는 일반적으로 @types를 설치한다)
외부 API의 타입 정보를 먼저 추가하자
마이그레이션을 할 때는 리팩터링을 하지 말자
타입스크립트에서는 클래스 멤버를 명시적으로 선언해야 한다.
객체는 한꺼번에 생성하는 방식, 또는 타입 단언문을 사용할 수 있다.
우선 마이그레이션이 중요하므로 단언을 사용할 수 있다.
테스트 코드는 항상 의존성 최상단에 위치한다. 따라서 테스트 코드 마이그레이션은 마지막 단계에 하면 된다. 하지만 마이그레이션 중에도 테스트는 수행할 수 있다.
아이템62
마이그레이션의 완성을 위해 noImplicitAny 설정하기
모든 파일이 .ts로 변환되었다면 noImplicitAny를 설정해 작업을 한다.
noImplicitAny를 전면 적용하기 전에 로컬에서부터 점진적으로 수정할 수 있다.
추후 점점 타입 체크의 강도를 높이면 된다.
- strictNullChecks
"strict": true