본문으로 바로가기

Typescript는 js의 슈퍼셋이며 js로 transpile합니다.

동적 타입 언어인 js를 정적 타입 언어로 사용할 수 있게 됩니다.

물론 동적 언어로 발생할 수 있는 에러를 테스트 코드의 커버리지를 높이는 방식으로 커버할 수도 있겠지만 굳이...

 

우선, Typescript는 공식 문서가 상당히 체계적으로 잘 정리되어 있습니다. 때문에 공식 문서로 공부하는 것을 추천해드립니다. 심지어 handbook은 번역까지 되어 있으니 참고합시다.

 

https://typescript-kr.github.io/

 

TypeScript 한글 문서

TypeScript 한글 번역 문서입니다

typescript-kr.github.io


yarn이든 npm이든 사용가능하나 가급적 npm 사용을 권장합니다.

npm init
npm install -g typescript // tsc 명령어로 버전 확인 가능
npm i -g ts-node // 트랜스파일하지 않고 ts를 곧바로 실행 가능

// 배포 환경을 위해 추가로 설치합시다.
npm i -D typescript
npm i -D @types/node

 

tsconfig.json 파일 생성 후 아래 내용 작성. tsconfig.json은 tsc를 실행하면 자동으로 찾아서 변환해주는 환경 설정입니다. tsc --init 명령어로도 사용할 수 있습니다.

tsc --init

 

compilerOptions에 대해서는 여기를 참고합시다.

(https://www.typescriptlang.org/docs/handbook/compiler-options.html)

{
  "compilerOptions": {
    "module": "CommonJS", // 트랜스파일한 결과물이 어떤 모듈 방식을 사용할 것인가?
    "target": "ESNext", // 어떤 버전으로 트랜스파일? (나중에 build시에는 모듈 번들러로 변환해줘야겠죠)
    "sourceMap": true
  },
  "include": ["src/*.ts"], 
  "exclude": ["node_modules"]
}

 

tsc 명령어 입력. 나중에 옵션을 많이 붙이게 된다면 package.json에서 명령어를 구성하면 됩니다.

tsc는 index.ts를 index.js, index.js.map으로 변환해줍니다. 정확히 말하면 '트랜스파일' 합니다.

트랜스파일과 컴파일은 종종 혼용되는 용어입니다. tsc는 typescript compile의 약자입니다.

tsc

 

tsc가 작동하지 않고 오류를 낸다면 다음 과정을 진행하자. 7까지 가는 도중 해결되는 경우가 많다.

1. 사전준비 vscode, node.js 설치

2. github등에서 리포지토리 작성후 vscode로 불러옴

3. npm install -g concurrently
npm install -g lite-server
npm install -g typescript

4. npm list -g --depth=0 입력후 3개의 패키지가 제대로 들어가 있는지 확인
예를들면 아래와 같은 결과가 나옵니다.

C:\Users\{사용자이름}\AppData\Roaming\npm +-- concurrently@5.0.0 +-- lite-server@2.5.4 `-- typescript@3.7.3

5. 4에서 확인한 npm의 경로를 복사후 환경설정의 PATH부분에 추가

6. VScode종료후 재시작하면 tsc입력시 정상작동합니다.

7. 이래도 안된다면 Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser 입력

 

그런데 매번 컴파일을 하는 것을 번거로운 일입니다. package.json에서 script를 추가해 이를 자동화하도록 합시다.

다음은 package.json을 복사해온 것입니다. 

추가된 내용은 scripts입니다. npm start 혹은 yarn start를 실행하면 prestart를 먼저 실행한 다음 start가 실행됩니다. 즉,  tsc(컴파일)된 후 node index.js 즉, index.js를 실행합니다.

 

여기서 알 수 있는 점은 node는 ts파일을 이해하지 못한다는 것입니다. 컴파일이 필요한 이유이기도 합니다.

 

아, 물론 개발 도중 확인 목적으로 컴파일하지 않고 ts-node로 실행할 수도 있습니다. 개발 시에는 굳이 컴파일하는데에 시간을 소비하지 맙시다.

 

// package.json
  "scripts": {
    "start": "node index.js",
    "prestart": "tsc"
  }

마지막으로, VSCode에서 진행하므로 TSLint extension도 설치해줍니다.

 

 

 


tsconfig

tsc --init을 통해 생성된 tsconfig는 디폴트값으로 설정되어 있습니다.

tsconfig : (https://www.typescriptlang.org/docs/handbook/tsconfig-json.html)

compilerOptions : (https://www.typescriptlang.org/docs/handbook/compiler-options.html)

compilerOptions 한국어 : (https://typescript-kr.github.io/pages/compiler-options.html)

공식 문서 (www.typescriptlang.org/tsconfig)

 

 

워낙 많은 옵션이 있기 때문에 하나하나 설명하는 것은 무리고, 중요하고 자주 사용하는 옵션(대개 compilerOptions) 먼저 설명하겠습니다. 물론 공식 문서에 다 나와있는 내용이고, 주석에도 설명이 다 되어있는 것들입니다.

 

tsconfig의 최상위 속성으로는 compilerOptions, files, include, exclude, compileOnSave, extends가 있습니다.

 

files는 컴파일할 대상 경로를 담은 리스트 배열입니다. files는 exclude보다 쎕니다. exclude를 먹어버린다는 말이죠. 이런 점 때문에 저는 잘 사용하지 않습니다.

 

include/exclude는 glob 패턴을 사용하여 트랜스파일할 혹은 제외할 대상을 정할 수 있습니다. include는 exclude보다 약합니다. include에 포함되어 있어도 exclude에 의해 제외할 수 있다는 것이죠. 

 

include/exclude의 편리한 점은, include에 *만 쓰고 확장자를 적지 않아도 자동으로 .ts .tsx. .d.ts 만 트랜스파일한다는 것입니다. js가 껴있다고 해서 오류를 내지는 않습니다.

 

또, exclude는 아무 설정을 하지 않아도 node_modules, bower_components, jspm_packages, outDir를 default로 제외합니다.

 

compilerOptions은 가장 많은 속성을 가지고 있습니다. tsc --init로 tsconfig.json을 만들면, 내부에 주석이 전부 있으므로 무슨 역할을 아는지 알 수 있습니다만 중요한 몇 가지 속성을 정리해보겠습니다.

 

 

 

"types": [], "typeRoots": []

www.typescriptlang.org/tsconfig#typeRoots

typing이 되어 있지 않은 라이브러리의 경우 typeRoots 설정 => https://darrengwon.tistory.com/964

 

TS 2.0 부터 가능해진 내장 type definition시스템으로 인해서 @types/.... 로 설치한 패키지는 types나 typeRoots를 설정해주지 않아도 기본적으로 자동으로 모두 읽어와서 활용하게 됩니다. 즉, node_modules/@types 내의 모든 경로를 찾아서 사용합니다. 

 

만약, 여러분들이 이용하는 외부 패키지가 타입을 제공하지 않으면 직접 타입을 만들어야 하는데, 이 경우에 다음과 같이 설정해놓은 후, 기본 definityle typed와 별도로 만들어준 타입을 동시에 사용하곤 합니다.

"typeRoots": ["./node_modules/@types", "./types"], 

 

여기서 중요한 점은 위와 같이 명시할 경우, 기본값인 ./node_module/@types도 명시해야 한다는 점입니다.

./node_modules/@types 경로를 주지 않으면 이 경로에 있는 패키지들이 설치되었다고 하더라도 사용하지 않습니다.

{
   "compilerOptions": {
       "typeRoots" : ["./typings"]
   }
}

This config file will include all packages under ./typings, and no packages from ./node_modules/@types.

즉, 기본값인 ./node_modules/@types도 명시하지 않으면 사용 하지 않는 다는 것입니다.

 

반면 types를 사용하면 node_modules/@types 내의 특정 모듈만 사용합니다. 사실 사용해본 적이 없네요.

{
   "compilerOptions": {
       "types" : ["node", "lodash", "express"]
   }
}

This tsconfig.json file will only include 

./node_modules/@types/node,

./node_modules/@types/lodash

./node_modules/@types/express.

만 사용하고 Other packages under node_modules/@types/* will not be included.

 

만약 types에 빈 배열 []을 넣는다면 node_modules/@types 내부에 있는 모든 패키지를 사용하지 않겠다는 선언이겠죠. 

여담으로, 요새는 @types 를 지원하지 않는 라이브러리도 d.ts(모듈 내부 타입 정의)를 포함해서 패키지를 배포하는 추세입니다.

 

 

module , moduleResolution

 

웹은 amd, 노드는 commonjs 방식으로 모듈 시스템을 사용합니다. 

module이 commonjs면 노드에서 작동하는 것을 의미하므로 moduleResoultion 키 값은 node이며 amd면 classic으로 설정합시다.

 

 

paths

 

import/from 문에서 어디서 소스 패키지를 찾을 것인지를 정합니다. node면 node_modules에서 저장하므로 해당 경로를 지정해주면 됩니다.

"paths": {
  "*": ["node_modules/*"]
} 

 

 

"target"

 

 Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'.

 

 

"lib": []

 

기본 type definition 라이브러리를 어떤 것을 사용할 것인지 결정합니다.

 

lib를 설정하지 않았을 때 target이 es3면 lib.d.ts를, es5면 dom, es5, scripthost를, es6면 dom, es6, dom.iterable, scripthost를 사용합니다.

 

고민할 필요도 없이 최신 문법을 쓰기 위해 다 때려 넣어도 됩니다.

커서를 올려놓고 가만히 있으면 어떤 것들을 넣을 수 있는지 확인할 수 있습니다.

React의 경우 lib에 dom을 반드시 추가해줘야 하는 등의 조건이 있지만 CRA를 통해 생성하면 알아서 다 세팅해줍니다.

"lib": ["es2015", "es2016", "es2017", "es2018", "es2019", "ESNext"],

 

 

"outDir""주소"

Redirect output structure to the directory. 

outDir를 지정한다고 폴더를 만들어주지는 않습니다. 직접 만들어야 합니다.

 

 

"outFile": "주소"

 

주의할 점이, Only 'amd' and 'system' modules are supported alongside --outFile입니다.

node는 기본적으로 commonjs를 차용하고 있으므로 저도 보통 module은 commonjs를 쓰기 때문에 outDir를 더 많이 사용합니다.

 

"removeComments" : Boolean

주석 모두 제거

 

"allowJs" : Allow javascript files to be compiled. ts 외에 js도 섞어 쓴다면 ㅇㅇ

"checkJs" : Report errors in .js files. js 파일에 있는 에러도 보고하라는 것이니 allowJS를 허용안하면 무용지물인 속성이다. 가급적 두 속성은 둘 다 키던지 둘 다 제거하자

 

 

"esModuleInterop"Boolean

 

 /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,

 

라이브러리 중에서는 amd 방식을 전제로 구현된 라이브러리가 있는데 commonjs 방식으로 동작하는 TS에서는 혼란을 줄 수 있습니다. 상호 운용적(interoperable)으로 사용하기 위해서는 true로 해놓아야 합니다.

 

// esModuleInterop: true일 경우 가능함
import React from "react";

// false인 경우 다음과 같이 import 해야 함
import * from React from "react;

 

"sourceMap"true

 

 /* Generates corresponding '.map' file. */,

트랜스파일 디렉터리에 .js.map 파일이 만들어진다. 소스맵 파일은 변환된 js코드가 ts의 어디에 해당하는 지를 알려준다.

 

 

"downlevelIteration"true 

 

/* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */,

제너레이터(function* {}, yeild...)를 사용하긱 위해서는 true로 둬야 합니다.

 

 

"noImplicitAny"false /* 

 

Raise error on expressions and declarations with an implied 'any' type. */,

아무래도 제일 유명한 속성입니다. true로 설정하면 자동으로 implicit하게 any를 넣어주지 않으므로 모든 곳에 타이핑을 해야 한다는 의미입니다. 설사 그것이 any라고 할지라도요.

 

typescript를 적용하는 궁극적인 목적을 달성하기 위해서는 noImplicit 시리즈를 모두 true로 둬야 합니다. 쉽지 않습니다.

 

 

"experimentalDecorators": true

"emitDecoratorMetadata": true

@Decorator를 사용하기 위해서 반드시 true로 둬야합니다!

 

 

strict 관련 설정들.

 

 

Typescript Language Server 

 

typescript를 설치했다면 node_modules 에 typescript 폴더 하단 bin에 tsc와 tsserver가 있는 것을 확인하실 수 있습니다. 당연히 tsc와 tsserver 명령어를 사용할수 있습니다.

 

vscode를 에디터로 사용하신다면 이미 tsserver가 내장되어 있습니다. typescript 설치를 안해서 잡아주는 이유가 여기에 있죠.

 

우리는 tsc를 이용해 ts를 js로 트랜스파일합니다. 사실 ts server 관련 내용을 단순 코더 입장에서는 다룰 이유가 없죠.

이제 tsc-watch를 활용해 tsc를 자동화해봅시다.

 

tsc-watch 사용하기

https://www.npmjs.com/package/tsc-watch tsc-watch The TypeScript compiler with onSuccess command www.npmjs.com 단도직입적으로 tsc-watch를 왜 사용하느냐 => nodemon과 같이 자동 실행을 해주기 때문이다...

darrengwon.tistory.com

 

 


darren, dev blog
블로그 이미지 DarrenKwonDev 님의 블로그
VISITOR 오늘 / 전체