본 글은 Typescript Programming을 요약한 글입니다.
자세한 내요은 본 책을 읽으시길 바랍니다.

 

 12장에서는 타입스크립트 응용 프로그램을 빌드하고 제품화하는 방법을 살펴본다.

  • 타입스크립트 응용 프로그램을 빌드하는 데 필요한 준비물
  • 서버에서 타입스크립트 응용 프로그램을 빌드하고 실행하기
  • 브라우저에서 타입스크립트 응용 프로그램을 빌드하고 실행하기
  • 타입스크립트를 빌드하고 NPM으로 발행하기

12.1 타입스크립트 프로젝트 빌드하기

 12.1.1 프로젝트 레이아웃

이 책에서는 타입스크립트 소스 코드를 최상위의 src/ 디렉터리에 저장하고, 컴파일한 결과 역시 최상위 dist/ 디렉터리에 저장할 것을 권장한다. 소스 코드와 생성된 코드를 두 개의 최상위 디렉터리에 분리할 수 있어서 다른 도구들과 통합하기가 편해진다. 또한 빌드 과정에서 만들어지는 부산물을 버전 관리 대상에서 제외하기 쉽다는 장점도 있다.

12.1.2 부산물

타입 파일 확장자 tsconfig.json 플래그 기본적으로 생성?
자바스크립트 .js {"emitDeclarationOnly": false} O
소스맵 .js.msp {"sourceMap": true} X
타입 선언 .d.ts {"declaration": true} X
선언 맵 .d.ts.map {"declarationMap": true} X
  1. 자바스크립트 파일 : TSC는 타입스크립트를 자바스크립트로 변환한다.
  2. 소스맵 : 생성된 자바스크립트 코드를 원래 타입스크립트 파일의 행과 열로 연결하는 데 필요한 특별 파일이다. 디버깅에 도움을 주고 자바스크립트 예외의 스택 추적값에서 가리키는 행과 열을 타입스크립트 파일에 매핑해준다.
  3. 타입선언 : 생성된 타입을 다른 타입스크립트 프로젝트에서 이용할 수 있도록 해준다.
  4. 선언 맵 : 타입스크립트 프로젝의 컴파일 시간을 단축하는 데 사용된다.

12.1.3 컴파일 대상 조정

자바스크립트는 매년 규격 명세가 새롭게 릴리스되면서 빠르게 진화할 뿐만 아니라 프로그래머 입장에서는 자신이 구현한 프로그램이 어떤 자바스크립트 번전을 지원하는 플랫폼에서 실행될지 보장할 수 없다. 더 나아가 많은 자바스크립트 프로그램은 단일 형태, 서버와 클라이언트 모두에서 실행할 수 있다.

  • 백엔드 자바스크립트 프로그램을 자신이 제어할 수 있는 서버에서 실행할때는 정확한 어떤 버전으로 실행할지 결정할 수 있다.
  • 백엔드 자바스크립트 프로그램을 오픈 소스로 릴리스한다면 소비자의 플랫폼에서 어떤 버전으로 실행할지 알 수 없다.
  • 자바스크립트를 브라우저에서 실행할 때는 사람들이 어떤 브라우저를 사용할지 알 수 없다.
  • 단일 구조의 자바스크립트 라이브러리를 릴리스한다면 가능한 한 낮은 버전의 Nodejs와 자바스크립트 엔진 및 버전을 동시에 지원해야한다.

모든 환경과 버전을 지원하는 것은 아니지만 코드는 가능하면 최신 버전으로 작성하는 것이 좋다. 이렇게 해도 구 버전 플랫폼에서 동작하게 할 수 있는데 두 가지 방법이 존재한다.

  1. 트랜스파일 : 최신 버전의 자바스크립트를 대상 플랫폼에서 지원하는 가장 낮은 자바스크립트 버전으로 변환한다.
  2. 폴리필 : 실행하려는 자바스크립트 런타임이 포함하지 않는 최신 기능을 폴리필로 제공한다.

TSC는 트랜스파일하는 기능을 기본으로 지원하지만 폴리필은 자동으로 해주지 않는다. TSC에서 대상 환경에 관한 정보를 설정하는 옵션은 세 가지다.

  • Target : 트랜스파일하려는 자바스크립트 버전을 설정한다.
  • module : 대상 모듈 시스템을 설정한다.
  • lib : 타입스크립트 대상 환경에서 어떤 자바스크립트 기능을 지원하는지 알려준다.

응용 프로그램을 실행할 환경의 자바스크립트 버전을 target에 설정하고, 어떤 기능을 쓸지는 lib에 설정한다. module 값은 대상 환경이 NodeJS냐 브라우저냐에 따라 달라지며, 브라우저 환경에서는 어떤 모듈 로더를 쓰는지를 고려해 정해야 한다.

 

target

TSC의 내장 트랜스파일러는 대부분의 자바스크립트 기능을 예전 자바스크립트 버전으로 변환할 수 있다. 트랜스파일 대상을 설정하려면 tsconfig.json 파일을 열어서 target 필드에 원하는 값을 채워 넣는다.

 

lib

 트랜스파일할 때 한 가지 유의사항이 있다. 대상 환경에서 새로운 기능을 지원하지 않으면 폴리필로 직접 제공해야 한다는 사실이다. 이런 폴리필을 우리가 직접 구현할 필요는 없다. core-js 같은 폴리필 라이브러리에서 필요한 기능을 설치하거나, @babel/polyfill을 설치한 . 후 바벨을 이용해 컴파일하면 타입스크립트가 타입을 확인하면서 필요한 폴리필을 자동으로 설치해준다.

 폴리필을 추가했으면 tsconfig.json의 lib 필드를 수정해서 해당 기능이 반드시 지원됨을 TSC에 알리도록 한다. 브라우저에서 실행할 때는 window, document 등 자바스크립트를 브라우저에서 실행할 때 필요한 API들을 사용할 수 있도록 DOM 타입 선언도 활성화해야 한다.

{
	"compilerOptions": {
    	"lib": [
        	"es2015",
            "es2016.array.includes",
            "dom"
        ]
    }
}

12.1.4 소스 맵 활성화

소스 맵은 트랜스파일된 코드를 원본 코드와 이어주는 정보를 제공한다. 대부분의 개발 도구, 에러 리포팅/로깅 프레임워크, 빌드 도구는 소스 맵의 존재를 이미 알고 있다. 보통 빌드 파이프라인은 처음 코드와는 상당히 다른 형태의 코드들을 중간중간 생성하기 때문에 파이프라인 곳곳에서 소스 맵을 활용하여 최종 자바스크립트의 디버깅을 휠씬 수월하게 처리해준다.

 개발 환경에서는 물론, 실제 제품에서도 브라우저와 서버 환경에 소스 맵을 함께 배포하면 좋다. 단점이 있다면 하나, 보안이 요구되는 상황이라면 고객용 브라우저 환경에는 소스 맵을 포함시키지 않는 편이 좋다.

12.1.5 프로젝트 참조

 응용 프로그램의 크기가 커지면 TSC가 타입을 확인하고 코드를 컴파일하는 데 더 오래 걸린다. 이 문제의 해법으로, TSC는 점진적 컴파일과 함께 프로젝트 참조라는 기능을 제공하여 컴파일 시간을 획기적으로 줄인다. 프로젝트 참조는 다음처럼 사용한다.

 1. 타입스크립트 프로젝트를 여러 프로젝트로 분리한다. 함께 수정될 가능성이 큰 코드들을 같은 디렉터리에 저장하는 방식으로 쪼갠다.

 2. 각 프로젝트 디렉터리에 최소한 다음 정보를 포함하는 tsconfig.json을 만든다.

{
	"compilerOptions": {
    	"composite": true,
        "declearation": true,
        "declarationMap": true,
        "rootDir": "."
    },
    "include": [
    	"./**/*.ts"
    ],
    "references": [
    	{
        	"path": "../myReferencedProject",
            "prepend": true
        }
    ],
}
  • composite: TSC에 이 디렉터리는 큰 타입스크립트 프로젝트의 서브 프로젝트임을 알려준다.
  • declaration: TSC에 이 프로젝트의 .d.ts 선언 파일을 생성하라고 지시한다. 각각의 프로젝트는 다른 프로젝트의 선언 파일과 생성된 자바스크립트 파일들에는 접근할 수 있지만, 원본 타입스크립트 파일에는 접근하지 못한다. 이렇게 하여 TSC가 타입을 다시 검사하거나 다시 컴파일해야하는 코드를 선택하는 기준이 만들어진다. 프로젝트 참조가 큰 프로젝트의 빌드 효율을 높여주는 핵심 원리다.
  • declarationMap: TSC에 생성된 타입 선언의 소스 맵을 빌드하라고 지시한다.
  • reference: 이 서브 프로젝트가 의존하는 다른 서브 프로젝트들의 목록이다.
    • 각 참조의 path는 tsconfig.json 파일이 담긴 디렉터리를 가리키거나, TSC 설정파일을 직접 가리켜야 한다.
    • prepend는 참조하는 서브 프로젝트에서 생성한 자바스크립트와 소스 맵을 이 서브 프로젝트에서 생성한 소스와 맵에 이어 붙인다.
  • rootDir: 이 서브 프로젝트가 루트 프로젝트(.)에 상대적으로 컴파일되어야 함을 명시한다.

 3. 아직 다른 서브 프로젝트에서 참조하지 않은 모든 서브 프로젝트를 참조하는 루트 tsconfig.json을 만든다.

{
	"files": [],
    "references": [
    	{
        	"path": "./myProject"
        },
        {
        	"path": "./mySecondProject"
        }
    ]
}

 

 4. 프로젝트를 컴파일할 때 프로젝트 참조를 활용하도록 bulid 플래그를 지정한다.

tsc --bulid # 또는 줄여서 tsc -b

12.1.6 에러 모니터링

타입스크립트는 컴파일 타임의 에러만 경고하므로 사용자가 런타임에 겪을 수 있는 에러를 컴파일 타임에 방지할 수 방법을 찾아야한다. Sentry,Bugsnag 같은 에러 모니터링 도구를 이용하면 런타임 예외를 보고하고 분석하는 데 도움이 된다.

12.2 서버에서 타입스크립트 실행

타입스크립트 코드를 NodeJS 환경에서 실행하려면 tsconfig.json의 module 플래그를 commonjs로 설정하고, 코드를 ES2015 자바스크립트로 컴파일한다. 그러면 ES2015의 import를 require로, export를 module.exports로 변환하여 NodeJS에서 추가 번들 없이 실행할 수 있도록 컴파일해준다. 소스맵도 NodeJS 프로세스에 제공해야 한다.

12.3 브라우저에서 타입스크립트 실행

브라우저에서 타입스크립트를 실행하려면 서버에서 보다 해야할 과정이 많다.

 

 1. 컴파일 하려는 모듈을 선택한다. 라이브러리를 발행할 때는 umd를 사용해 다양한 모듈 번들러와의 호환성을 극대화해야한다. 발행 계획이 없다면 사용하는 모듈 번들러에 맞는 포맷으로 컴파일하면 되니 해당 번들러의 문서를 확인해 본다.

 

 2. 모든 타입스크립트 파일으 한 개의 자바스크립트 파일이나 자바스크립트 파일 집합으로 컴파일하도록 빌드 파이프라인을 설정한다. TSC는 빌드 플러그인이나 웹팩이 제공하는 정도로 영리한 코드 분할을 제공하지 않으므로 자체 기능으로는 부족하다 사실을 느낄 것이다. 그렇기에 처음부터 강력한 빌드 도구를 사용하느 것이 바람직하다.

  • 빌드 도구가 프로젝트 의존성 그래프를 더 정확하게 분석할 수 있도록, 코드를 모듈로 유지하고 코드에서 임의의 의존성을 피한다.
  • 동적 임포트를 이용하여 게으르게 로딩하면 첫 페이지 렌더링 속도를 높일 수 있다.
  • 자동 코드 분할 기능을 사용하면 페이지 로딩이 불필요하게 느려지지 않는다.
  • 페이지 로딩 시간을 측정하는 수단을 마련한다.
  • 제품 빌드를 가능한한 개발 빌드와 같은 형태로 유지한다.
  • 빠진 브라우저 기능을 폴리필로 제공하는 대책을 마련한다.
    • 모든 번들에 폴리필로 제공하는 표준 집합을 마련하거나
    • 브라우저가 지원하는 기능이 무엇이냐에 따라 동적으로 필요한 폴리필을 마련할 수 있다.

12.4 타입스크립트 코드를 NPM으로 발행하기

타입스크립트를 다른 누군가가 사용하도록 컴파일 할때는 다음 규칙들을 따르는 것이 좋다.

  • 자신의 코드를 쉽게 디버깅할 수 있도록 소스 맵을 생성한다.
  • 다른 사람이 우리의 코드르 쉽게 빌드하고 실행할 수 있도록 ES5로 컴파일한다.
  • 어떤 모듈 타입으로 컴파일할지 주의 깊게 결정한다.
  • 다른 타입스크립트 사용자가 우리 코드의 타입을 얻을 수 있도록 타입 선언을 생성한다.

다음과 같은 과정을 거친다.

  1. 먼저 tsc로 타입스크립트를 자바스크립트로 컴파일하고 대응하는 타입선언을 생성한다.
  2. 이어서 NPM에 발행하지 않을 타입스크립트 코드 목록을 .npmignore 파일에 기재하여 패키지가 너무 커지지 않도록한다. 그리고 .gitignore 파일에는 부산물을 제외하게끔 설정해서 깃 저장소가 불필요한 파일로 오염되는 일을 방지한다.
  3. 마지막으로 프로젝트의 package.json에 "types" 필드를 추가해서 타입 선언이 제공될 것임을 알려준다. 스크립트도 추가해서 패키지의 자바스크립트, 타입선언, 소스 맵이 항상 원본 타입스크립트와 같은 최신 버전이 되도록 만든다.

12.5 세 슬래시 지시어

이 지시어는 특별한 포맷의 타입스크립트 주석으로, TSC에 명령을 하달한다. types는 타입 전용 전체 모듈 임포트를 생략할 때 사용하고, amd-module은 생성된 AMD 모듈의 이름을 정할 때 사용한다.

12.5.1 types 지시어

 모듈에서 무언가를 임포트한 코드를 자바스크립트로 컴파일 할 때 타입스크립트가 항상 import나 require 호출을 생성하는 것은 아니다. export한 대상들이 모듈에서 오직 타입 위치에서만 쓰인다면, 타입스크립트는 해당 import 문에 해당하는 자바스크립트 코드를 전혀 생성하지 않는다. 임포트된 대상들이 타입 수준에서만 존재한다고 생각하기 때문이다. 이 기능을 임포트 생략이라고 부른다.

12.5.2 amd-module 지시어

 타입스크립트 코드를 AMD 모듈 포맷으로 컴파일할 때 타입스크립트는 기본값으로 익명 AMD 모듈을 생성한다. 이때 코드에서 amd-module 세 슬래시 지시어를 추가해주면 AMD 모듈에 이름을 지어줄 수 있다.

// <amd-module name="LogService" /> 1
export let LogService = { // 2
	log() {
    	// ...
    }
}
  1. amd-module 지시어에 name 속성을 설정했다.
  2. 나머지 코드는 그대로이다.

TSC로 AMD 모듈 포맷으로 컴파일하면 다음의 자바스크립트 코드가 생성된다.

// <amd-module name="LogService" /> 1
definde('LogeService', ['require','exports'], function(require, exports){ // LogeService라는 이름이 생겼다
	// .... 
})

AMD로 모듈로 컴파일할 떄는 코드를 번들링하거나 디버깅하기 쉽도록 amd-module 지시어를 사용하자.

본 글은 Typescript Programming을 요약한 글입니다.
자세한 내요은 본 책을 읽으시길 바랍니다.

 

 이번 11장에서는 타입을 쓰지 않는 언어, 즉 서드 파티 자바스크립트 라이브러리를 사용한다거나 빠른 패치를 위해 타입 안전성을 포기하는 등의 실전 상황에서 타입스크립트를 접목하는 방법을 알아보려한다.

  1. 타입 선언 사용하기
  2. 자바스크립트에서 타입스크립트로 점진적으로 마이그레이션하기
  3. 서드 파티 자바스크립트와 타입스크립트 사용하기

11.1 타입선언

타입 선언은 d.ts 확장자를 가진 파일이다. JSDoc 어노테이션과 더불어, 타입 선언은 타입이 없는 자바스크립트 코드에 타입스크립트 타입을 부여할 수 있는 수단이다. 타입 선언은 일반 자바스크립트와 비슷하지만 몇 가지 차이점이 존재한다.

  • 타입만 포함할 수 있고 값은 포함할 수 없다.
  • 값을 정의할 수 없지만, declare라는 특별 키워드를 사용해 다른 어딘가에 값이 있다는 사실을 선언할 수 있다.
  • 소비자가 볼 수 있는 대상에만 타입을 선언할 수 있다. 노출되지 않은 타입이나 함수 안에 선언된 지역 변수의 타입은 포함할 수 없다.
import {Subscriber} from './Subscriber'
import {Subscription} from './Subscription'
import {PartialObserver, Subscribable, TeardownLogic} from './types'

export declare class Observable<T> implements Subscribable<T> { // 1
	// ...
    // ...
    ):Subscription // 2
}
  1. 타입 선언에선 클래스를 직접 정의할 수는 없지만, 그 대신 .d.ts 파일에 대응하는 자바스크립트 파일 안에 정의했음을 선언(declare)할 수 있다.
  2. 타입 선언은 구현을 포함하지 않으므로 subscrive의 오버로드 두 개만 포함하고 구현 시그니처는 포함하지 않는다.

 자세히 보면 Observable.ts에서 구현을 빼면 Observable.d.ts가 된다는 사실을 확인할 수 있다. 라이브러리의 다른 파일에서는 직접 Observable.ts 타입스크립트 파일에 접근하고 필요한 기능을 사용할 수 있으므로 이런 타입 선언이 전혀 필요가 없다. 하지만 타입스크립트 응용 프로그램에서 라이브러리를 사용할 때는 상황이 다르다.

 

타입 선언 파일은 다음처럼 활용된다.

  1. 다른 사용자가 타입스크립트 응용 프로그램에서 우리가 만든 컴파일한 타입스크립트를 사용한다면 그들의 TSC 인스턴스는 우리의 타입스크립트로부터 생성된 자바스크립트 파일에 대응하는 d.ts 파일을 검색한다.
  2. 타입스크립트가 지원하는 코드 편집기는 이 .d.ts 파일들을 읽어 해석한 다음 우리가 코드를 작성할 떄 유용한 타입 힌트를 제공한다.
  3. 불필요한 재컴파일을 막아주어 컴파일 시간을 크게 줄여준다.

타입 선언은 타입스크립트에 "자바스크립트에는 이런 정보가 정의되어 있다"라고 알려주는 수단이다. 때로는 값을 포함하는 일반적인 선언과 구별하기 위해 타입 선언에 앰비언트라는 표현을 쓰기도 한다. 타입 선언은 다음과 같은 상황에서 사용할 수 있다.

  • 자바스크립트 어딘가에 전역 변수가 정의되어 있음을 타입스크립트에 알림
  • 프로젝트 어디에서나 전역으로 이용할 수 있는 타입을 정의하여 임포트 없이 바로 사용하고자 할 때
  • 타입스크립트에 NPM으로 설치한 서드 파티 모듈이 있음을 알릴 때

어떤 목적으로 사용하든 타입 선언은 스크립트 모드의 .ts나 .d.ts 파일 안에 위치해야 한다. 또한 타입 선언 파일에 선언된 최상위 수준 '값'에는 declare 키워드를 사용해야 하지만 최상위 수준 '타입'과 '인터페이스'에서는 사용하지 않아도 된다.

11.1.1 앰비언트 변수 선언

엠비언트 변수 선언은 한 프로젝트의 모든 .ts와 d.ts 파일에서 임포트 없이 사용할 수 있는 전역 변수의 존재를 타입스크립트에 알리는 수단이다.

declare let process: {
	env: {
    	NODE_ENV: 'development'|'production'
    }
}

process = {
	env: {
    	NODE_ENV: 'production'
    }
}

프로그램이 어느 순간 process.env.NODE_ENV를 확인한다고 가정할 때, process라는 전역객체가 있고, 이 객체는 한 개의 env 프로퍼티를 가지고 있으며 env는 NODE_ENV라는 프로퍼티를 갖고 있음을 타입스크립트에 선언하면 에러없이 처리할 수 있다.

11.1.2 앰비언트 타입 선언

엠비언트 타입 선언은 앰비언트 변수 선언과 같은 규칙을 준수한다. 즉, 선언은 스크립트 모드 파일의 .ts나 .d.ts 파일에 저장해야 하며 명시적으로 임포트 하지않아도 프로젝트의 모든 파일에서 전역으로 이용할 수 있다.

 예를 들어, 배열이 아니면 배열로 전환해주는 전역 유틸리티 타입 ToArray<T>가 있다고 가정할 때 같은 프로젝트의 모든 스크립트 모드 파일에서 이 타입을 정의할 수 있다. 최상우 수준의 types.ts 파일에 정의 한다면 다른 파일에서 명시적으로 임포트 하지 않고도 이타입을 사용할 수 있다.

// types.ts
type ToArray<T> = T extends unknown[] ? T : T[]


// 다른 파일
function toArray<T>(a:T): ToArray<T>{
	// ...
}

11.1.3 앰비언트 모듈 선언

자바스크립트 모듈을 사용하면서 그 모듈에서 사용할 일부 타입을 빠르게 선언하고 안전하게 사용하고 싶다면 앰비언트 모듈 선언을 사용하자. 앰비언트 모듈 선언은 평범한 타입 선언을 declare module이라는 특별한 문법으로 감싸는 것이 특징이다.

declare module 'module-name' {
	export type MyType = number
    export type MyDefaultType = { a : string}
    export let myExport : MyType
    // ...
}

 모듈명은 정확한 import 경로에 대응한다. 이 경로를 임포트하면 앰비언트 모듈 선언이 타입스크립트에 무엇을 이용할 수 있는지 알려준다. 중첩된 모듈이 있다면 선언에 import 경로 전체를 포함해야 한다.

import ModuleNmae from 'module-name'
ModuleName.a // string

declare module '@most/core' {
	// 타입 선언
}

모듈 선언은 와일드카드 임포트를 지원하므로 '주어진 패턴과 일치하는 모든 import 경로' 특정한 타입으로 해석하도록 할 수 있다. 와일드 카드를 이용해 import 경로에 패턴을 부여해보자

// 웹팩의 json 로더로 임포트한 JSON 파일의 타입 선언
declare module 'json!*' {
	let value: object
    export default value
}

// 웹팩의 스타일 로더를 임포트한 CSS 파일의 타입 선언
declare module '*.css' {
	let css: CSSRuleList
    export default css
}

// 다른 파일에서 json, css 파일을 로드 할 수 있디.
import a form 'json!myFile'
import b form './widget.css'
a // 객체
b // CSSRuleList

11.2 자바스크립트를 타입스크립트로 천천히 마이그레이션하기

이는 다음의 과정을 거쳐야한다.

  1. TSC를 프로젝트에 추가한다.
  2. 기존 자바스크립트 코드에 타입 확인을 시작한다.
  3. 한 번에 한 파일씩 자바스크립트를 타입스크립트로 마이그레이션한다.
  4. 의존하는 외부 코드용 타입 선언을 설치한다. 
    1. 아직 타입이 없는 외부 코드용 타입의 스텁 만들기
    2. 타입 선언을 만들어서 DefinitelyTyped에 기여하기
  5. 코드베이스에 strict 모드를 적용한다.

11.2.1 TSC 추가

 타입스크립트와 자바스크립트가 함께 사용된 코드베이스에서는 TSC가 타입스크립트뿐 아니라 자바스크립트 파일도 컴파일하도록 설정한다. tsconfig.json을 다음처럼 설정하자.

{
	"compilerOtions":{
    	"allowJS": true
    }
}

 이처럼 설정 하나만 바꾸면 TSC가 자바스크립트 파일도 컴파일한다.

11.2.2.1 자바스크립트에 타입 확인 활성화(선택사항)

TSC가 자바스크립트를 처리하기 시작했으므로 타입 확인 기능을 이용할 수 있다. tsconfig.json을 다음처럼 설정하자.

{
	"compilerOtions":{
    	"allowJS": true
        "checkJS": true
    }
}

이제 타입스크립트가 자바스크립트 파일을 컴파일할 때마다 마치 타입스크립트 코드를 다루듯 최선을 다해 타입을 추론하고 검증한다.

 

타입스크립트로 자바스크립트를 실행하면 타입스크립트 코드를 실할 때보다 더 관대한 추론 알고리즘을 적용한다.

  • 모든 함수 매개변수는 선택사항이다.
  • 함수와 클래스의 프로퍼티 타입은 어떻게 선언했는지가 아니라 어떻게 사용했는지에 의해 결정된다.
  • 객체, 클래스, 함수를 선언한 다음에 추가 프로퍼티를 할당할 수 있다.내부적으로 타입스크립트는 각 클래스와 함수 선언에 대응하는 네임스페이스를 생성하고 모든 객체 리터럴에 인덱스 시그니처를 자동 추가해서 이를 구현한다.

11.2.2.2 JSDoc 어노테이션 추가(선택사항)

 급한 상황에서는 기존의 자바스크립트 파일에 추가한 새 함수에만 타입 어노테이션을 추가하고 싶을 수 있다. 이럴 때는 이 파일을 타입스크립트로 변환하기 전까지는 JSDoc 어노테이션을 새 함수에 적용할 수 있다. 타입스크립트는 JSDoc을 이해하며, 타입 검사기에 타입 정보를 알려주는 용도로 쓰인다.

11.2.3 파일 이름을 .ts로 바꾸기

 한 번에 한 파일만 선택하여 확장자를 .js에서 .ts로 바꾼다. 이 순간 에러가 나타나면서 확인되지 않은 타입에러, 누락된 case 문, null 확인 누락, 잘못된 변수 이름 등을 알려준다. 이런 에러를 해결하는 방법은 두 가지다.

  1. 제대로 처리하기. 관련된 모든 파일에서 더 이상 에러가 발생하지 않도록 차분하게 형태, 필드, 함수의 타입을 올바르게 결정한다
  2. 빠르게 처리하기. 닥치는 대로 자바스크립트의 파일 확장자를 .ts로 바꾸되 tsconfig.json 설정은 느슨하게 유지해서 가능한 한 타입 에러가 적게 발생하도록 설정하자.

11.2.4 엄격하게 만들기

TSC의 엄격성과 관련된 플래그를 한 개씩 설정해가면서 코드를 최대한 안전하게 만들 차례다. 마지막에는 TSC의 자바스크립트 상호 운용 플래그를 꺼서 모든 코드가 엄격한 타입의 타입스크립트가 되도록 강제한다.

{
	"compilerOtions":{
    	"allowJS": false
        "checkJS": false
    }
}

11.3 자바스크립트의 타임 검색

타입스크립트 파일에서 자바스크립트 파일을 임포트할 떄 타입스크립트는 다음 알고리즘을 토대로 자바스크립트 코드에 필요한 타입 선언을 검색한다.

  1. js 파일과 이름이 같은 형제 .d.ts. 파일을 찾는다. 이 파일이 존재함녀 .js 파일의 타입 선언으로 사용한다.
  2. 적절한 d.ts 파일이 없고, 만약 allowJS와 checkJS가 true이면 .js 파일의 타입을 추론한다.
  3. 2에도 해당하지 않으면 전체 모듈을 any로 처리한다.

 

서드 파티 자바스크립트 모듈를 임포트 할 떄는 조금 다른 알고리즘을 사용한다.

  1. 모듈의 지역 타입 선언이 존재한다면 그 선언을 사용한다.
  2. 지역 타입 선언이 존재하지 않는다면 모듈의 package.json을 확인한다. types나 typigns라는 필드가 정의되어 있으며 해당 필드가 가리키는 .d.ts 파일을 모듈의 타입 선언 소스로 사용한다.
  3. 아니면 한 번에 한 단계씩 상위 디렉터리로 이동하면서 node_modules/@types 디렉터리를 찾는다.
  4. 그래도 타입 선언을 찾지 못했다면, 앞서 설명한 지역 타입 찾기 알고리즘을 수행한다.

11.4 서드 파티 자바스크립트 사용

서드 파티 자바스크립트 코드를 프로젝트에 설치할 때 다음처럼 세 가지 상황이 일어날 수 있다.

  1. 코드를 설치할 때 타입 선언이 함께 제공됨
  2. 코드를 설치할 때 타입 선언은 제공되지 않지만 DefinitelyTyped에서 선언을 구할 수 있음
  3. 코드를 설치할 때 타입 선언은 제공되지 않지만 DefinitelyTyped에서도 선언을 구할 수 없음

11.4.1 타입 선언을 포함하는 자바스크립트

설치하기만 하면 곧바로 타입 지워늘 완벽하게 받을 수 있다.

11.4.2  DefinitelyTyped에서 타입 선언을 제공하는 자바스크립트

임포트하는 서드 파티 코드가 자체적으로 타입 선언을 포함하지 않더라도 타입스크립트 커뮤니티를 관리하는 엠비언트 모듈 선언 중앙 저장소인 DefinitelyTyped에서 타입 선언을 제공하기도 한다. 설치한 패키지의 타입 선언이 DefinitelyTyped에 있는지 확인하려면 Typed Search에서 검색해보거나, 곧바로 선언이 설치되는지 시도해보자.

pnpm i lodash --save # lodash 설치
pnpm i @types/lodash --save-dev # lodash의 타입 선언 설치

--save-dev 플래그를 설정하면 설치한 타입 선언을 pak-age.json의 devDependencies 필드에 추가해준다.

11.4.3 DefinitelyTyped에서 타입 선언을 제공하지 않는 자바스크립트

 위 세 가지 상황 중 가장 드문 상황이다. 이를 해결하기 위한 다양한 선택지가 존재한다.

  1. 타입을 사용하지 않는 임포트 윗줄에 @ts-ignore 지시어를 추가해서 해당 임포트를 화이트리스트 처리한다.
  2. 빈 타입 선언 파일을 하나 만들어서 화이트리스트를 처리할 모듈을 적어 놓는다. 이렇게 해서 타입스크립트에 임포트 할 수 있는 모듈이 존재함을 알려주지만 어떤 타입을 포함하는지는 알려주지는 않는다.
    타입을 사용하지 않는 모든 모듈 정보를 한 파일에 둔다는 점에서 첫 번째 방법보다는 낫지만 그 안의 모든 export의 타입은 여전히 any이므로 안전성 면에서는 조금의 차이도 없다.
  3. 엠비언트 모듈 선언을 만든다. tpye.d.ts라는 파일을 만들고 빈 선언을 추가한다. 그리고 타입 선언을 채운다.
  4. 3번째 방법으로 만든 타입 선언을 다른 개발자들도 이용할 수 있도록 NPM에 제공한다.

서드 파티 자바스크립트의 타입 선언은 간단하게 구현할 수 있지만 어떻게 구현하는지는 모듈 유형에 따라 달라진다. 부록 D에서 알아보자

+ Recent posts