[8장] 타입스크립트로 마이그레이션하기
이펙티브 타입스크립트 8장을 정리한 내용입니다.
작성일 2024.02.14
페이지가 생성된 시간 2024.10.01 21:01:05

0

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
©2024 dlwl98
github
PostsAbout