[TypeScript] tsconfig.json

유동균·2023년 2월 10일
0

TypeScript

목록 보기
2/3
post-thumbnail

1. package.json 만들기

타입스크립트 개발은 Node.js 프로젝트를 만든 다음, 개발 언어를 타입스크립트로 설정하는 방식으로 진행.

  • package.json 만들기
    • package.json은 Node.js가 관리하는 패키지 관리 파일로서 프로젝트 정보와 관련 패키지가 기록됨
> npm init -y
Wrote to......

2. 패키지 설치하기

> npm i -D typescript ts-node @types/node

--save (-S)
프로젝트를 실행할 때 필요한 패키지로 설치.
패키지 정보가 package.json 파일의 "dependencies"에 등록
--save-dev (-D)
프로젝트를 개발할 때만 필요한 패키지로 설치.
패키지 정보가 package.json 파일의 "devDependencies"에 등록

2.1 ts-node

  • Typescript로 작성된 앱을 브라우저 외부에서 실행할 수 있게 해주는 Node.js 패키지
  • Typescript는 코드작성을 마친후, javascript로 변환(컴파일)되는데,
  • Node.js에서는 javascript만 사용하므로, 변환 -> 실행해야 하는 번거로움이 있다.
  • ts-node는, 이 변환 -> 실행 작업을 한번에 해준다.

2.2 @types/node

  • TypeScript를 사용할 때 Node.js 관련 정의 파일을 제공하는 패키지.
  • Node.js의 전역 변수, 모듈, 콜백 함수 등에 대한 타입 정보를 갖고 있어서 TypeScript를 사용하는 개발자들이 Node.js 관련 코드를 개발할 때 타입 정보를 제공받아, 오류를 예방하고 코드의 가독성을 높일 수 있다.

2.3 ts-node-dev

  • 여전히 배포를 하기위해서는 따로 자바스크립트로 컴파일을 해야하기 때문에 따로 tsc 명령어를 이용해 js로 변환해주어야한다.
  • ts-node-dev 는 ts-node 와 node-dev 를 합본팩

node-dev
nodemon과 같은 watch(실시간 동작) 관련된 모듈

> npm i -D ts-node-dev

> ts-node-dev --respawn --transpile-only index.ts
## 축약 > tsnd --respawn server.ts
  // 개발환경 구성, package.json scripts 항목
 
  "scripts": {
     // 전체 ts 파일들을 컴파일
     "build": "tsc", 

     // 실시간 ts 컴파일
     "build:watch": "tsc -w", 

     // nodemon 실행
     // --watch src/ : src 폴더안에 변화가 있으면 감지해서 재시작함
     // --exec ts-node : ts파일을 nodemon으로 실행시킬 수 있게함
     "dev": "NODE_ENV=dev nodemon --watch src/ --delay 500ms --exec ts-node src/start.ts", 

     // ts-node-dev 실행
     // dev 환경에서 ts파일로 서버 실행
     "start:dev": "NODE_ENV=dev ts-node-dev --respawn --transpile-only src/start.ts",

     // ts를 빌드한 js file로 node 서버 시작
     "start": "NODE_ENV=production node build/start.js"
  }

3. tsconfig.json 만들기

  • tsconfig.json은 타입스크립트를 자바스크립트로 변환할 때의 컴파일 설정을 정의 해놓는 파일.
  • 프로젝트를 컴파일 하는데 필요한 루트 파일, 컴파일러 옵션 등을 상세히 설정할 수 있다.
  • 보통 tsconfig.json 파일은 TypeScript 프로젝트의 루트 디렉토리(Root Directory)에 위치된다.
  • tsconfig에서 옵션들을 정의해 놓으면, 더이상 컴파일 할때 대상 파일이나 옵션을 지정하지 않아도 된다.
> tsc --init
  • --init 으로 생성한 파일에 미리 써져있는건 tsc 명령어의 옵션들(compilerOptions)이고, 이외에도 몇몇 전역 설정 파일 속성들이 존재한다.

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

컴파일 대상 경로를 정의하는 속성의 우선 순위 files > include = exclude

{
   "compilerOptions": { 
   	  "target": "es2016" 
      // ... options 
   },
 
   "files": ["app.ts", "./utils/math.ts"],
 
   "include": ["src/**/*"] ,  	
 
   "exclude": ["node_modules", "**/*.(spec|test).ts"],
 
   "extends": "./config/base",
}

3.1 compilerOptions

  • 컴파일러 옵션
  • 컴파일 대상 파일들을 어떻게 변환할지 세세히 정하는 옵션.

아래의 옵션들은 자주 사용하는 옵션들

3.1.1 Language and Environment 옵션

3.1.1.1 target

  • 어떠한 버전의 JavaScript 코드로 컴파일 할지 지정한다.
  • 만약 코드가 구식의 환경에서 배포된다면 더 낮은 버전을 지정해야 하고, 신식의 환경에서만 배포된다는 보장이 있다면 더 높은 타겟으로 지정해도 된다.
    (자바스크립트 버전 지정 값을 넣지 않으면 default로 es5로 컴파일 된다)
  • 다만 타입스크립트 소스 코드에 Promise 코드가 있을 경우, 이는 ES5에서 지원해주지 않기 때문에 Typescript를 컴파일 하면 오류가 발생하니 이부분은 유의해야 한다.
  • 대부분의 브라우저는 모든 ES6를 지원하기 때문에, 보통 ES6로 놓고 사용되는 편이다.
  • target 프로퍼티는 lib 프로퍼티의 기본값도 자동으로 결정 시킨다.
  • 따라서 target 프로퍼티와 lib 프로퍼티를 권장되는 방식대로 직접 맞출 수도 있지만, 편의를 위해 그냥 target 프로퍼티만 지정할 수도 있다.
  • target 프로퍼티 값중에 ESNext 옵션값이 있는데, 가장 최신 기능의 자바스크립트 버전을 가리키는 값이다.(이 설정은 주의 깊게 사용되어야 하는데, 왜냐하면 현재 TypeScript의 버전에 따라 ESNext가 가리키는 버전이 달라질 수 있기 때문이다.)
      "compilerOptions": {
          "target": "ES6" // 어떤 버전의 자바스크립트로 컴파일 될 것인지 설정
          // 'es3', 'es5', 'es2015', 'es2016', 'es2017','es2018', 'esnext' 가능
      }

3.1.1.2 lib

  • lib 옵션은 컴파일에 필요한 JavaScript 내장 라이브러리를 지정할 수 있다.
  • 이 프로퍼티가 지정되어 있지 않다면 target 프로퍼티에 지정된 버전에 따라 필요한 타입 정의들에 대한 정보가 자동으로 지정된다.
  • 예를 들어, target 프로퍼티가 ES6 혹은 그 이상의 버전으로 지정되었는데, lib 프로퍼티가 지정되지 않다면 자동으로 lib 프로퍼티에는 ES2015(lib.es2015.d.ts 파일) 등의 라이브러리들이 지정되기 때문에 기본적으로 타입 정보를 전역으로 참조할 수 있게 되는 것이다.
  • lib 프로퍼티를 지정하지 않을 때 자동으로 설정되는 값은 다음과 같다.
    • target이 es3이면 디폴트로 lib.d.ts를 사용
    • target이 es5이면, 디폴트로 dom, es5, scripthost를 사용
    • target이 es6이면, 디폴트로 dom, es6, dom.iterable, scripthost를 사용
    "compilerOptions": {
        "lib": ["es5", "es2015.promise", "dom"], // 컴파일 과정에 사용될 라이브러리 파일 설정
      
        /*
        es5: global type을 사용하기 위함 (Array, Boolean, Function 등..)
        es2015.promise: Promise를 사용하기 위함
        dom: setTimeout, console.log 등 dom에서 지원해주는 기능들을 사용하기 위함
        */
    }

3.1.1.3 experimentalDecorators, emitDecoratorMetadata

  • 타입스크립트의 @Decorator를 사용하기 위해서는 true로 둬야 작동된다.
"compilerOptions": {
  "experimentalDecorators": true /* ES7 데코레이터(decorators) 실험 기능 지원 설정 */
  "emitDecoratorMetadata": true /* 데코레이터를 위한 유형 메타데이터 방출 실험 기능 지원 설정 */
}
function methodDecorator() {
   console.log('method');
   return function (target: any, property: any, descriptor: any) {};
}
 
function propertyDecorator(writable: boolean = true) {
   console.log('property');
   return function (target: any, decoratedPropertyName: any): any {};
}
 
class Test {
   @propertyDecorator()
   property = 'property';
 
   @methodDecorator()
   test(param1: string) {
      console.log('test1');
   }
}

3.1.1.4 jsx

  • .tsx 확장자의 컴파일 결과 JSX 코드를 어떻게 컴파일할지 결정한다.
    • react : .js 파일로 컴파일 된다. (JSX 코드는 React.createElement() 함수의 호출로 변환됨)
    • react-jsx : .js 파일로 컴파일 된다. (JSX 코드는 _jsx() 함수의 호출로 변환됨)
    • react-jsxdev : .js 파일로 컴파일 된다. (JSX 코드는 _jsx() 함수의 호출로 변환됨)
    • preserve : .jsx 파일로 컴파일 된다. (JSX 코드가 그대로 유지됨)
    • react-native : .js 파일로 컴파일 된다. (JSX 코드가 그대로 유지됨)
"compilerOptions": {
	"jsx": "preserve" // tsx 파일을 jsx로 어떻게 컴파일할 것인지 'preserve', 'react-native', 'react'
}

.js vs .jsx

  • '확장자로서의 차이가 없다'
  • 하지만 JSX는 자바스크립트 표준 문법이 아니기에 논쟁이 있을 수 있다.
  • 리액트로 작성한 코드들은 자바스크립트로 변환된되기 때문에 컴포넌트 파일을 만들어 사용하는 리액트의 JSX 관련 코드는 .jsx로 만들고 나머지 일반 JavaScript 코드들은 .js로 만들면 된다.

.ts vs .tsx

  • 자바스크립트 외에 타입스크립트의 경우, .ts.tsx 확장자로 사용한다.
  • .tsx 에서는 JSX 문법을 사용할 수 있지만,
  • .ts는 JSX 문법이 불가능하다. 오직 TypeScript만 사용 가능하다.

3.1.2 Modules 옵션

3.1.2.1 rootDir

  • 루트 디렉토리 기준을 변경한다. js 아웃풋 경로에 영향을 줄 수 있다.

3.1.2.2 module, moduleResolution

  • 프로그램에서 사용할 모듈 시스템을 결정한다.
  • 만일 import 구문을 es6로 컴파일 했을때, 동일하게 import로 컴파일되어 commonJS환경의 node로 실행시 오류가 발생 할 수도 있다.
  • 따라서 import 구문을 require 구문으로 컴파일을 해줘야할때 module의 속성값을 commonJS로 지정하면 된다.
    • CommonJS (target 프로퍼티가 ES3 혹은 ES5로 지정되었을 때의 기본값)
    • ES6/ES2015 (target 프로퍼티가 ES6 혹은 그 이상의 버전으로 지정되었을 때의 기본값)
    • 나머지 (ES2020, ESNext, AMD, UMD, System, None)
  • 참고로 module 프로퍼티는 moduleResolution 프로퍼티의 기본값도 결정한다.
  • module이 commonjs면 노드에서 작동하는 것을 의미하므로, moduleResoultion 키 값은 node이며, 만일 module이 amd(웹)면 classic으로 설정된다.
"compilerOptions": {
	"module": "commonjs", /* 생성될 모듈 코드 설정: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
    "moduleResolution": "node", /* 모듈 분석 방법 설정: 'node' (Node.js) 또는 'classic' (TypeScript pre-1.6). */
}

3.1.2.3 baseURL, paths

  • import 구문의 모듈 해석 시에 기준이 되는 경로를 지정한다.
  • 개발을 하다 보면, 노드 패키지 이외에도, 직접 만든 소스 파일을 import 시켜야 하는 때가 발생한다.
  • 그래서 파일의 상단에는 다음과 같이 전역경로 와 상대경로 기준으로 각각 import 하게 된다.
import styled from 'styled-components'; // 노드 패키지일 경우 최상단 경로에 있는 node_modules 폴더를 자동 인식
import { TextField } from '../../../../components/textfield'; // 직접 만든 사용사 소스 파일이 있을 경우 상대경로로 가져와야 한다.
 
...
  • ../../../../index.ts같이 import 하는 이런 방식이 좀 예쁘진 않아도 일단 작동하는데는 문제가 없지만, 추후 계속 프로젝트를 작성하거나 리팩토링 할 때 문제가 발생할 수 있다.
  • 예를들어 상대 경로란 현재 위치하고 있는 파일 경로에 따라 얼마든지 달라질수가 있기 때문에, 만일 다른 경로에 파일을 만들어서 동일한 모듈을 import 하려고 하면, 위치 기준점이 달라지기 때문에 다르게 상대경로를 찾아 들어가야 되서 굉장히 번거로워 진다.
  • 바로 이때 baseUrl 속성 과 paths 속성을 설정하면 절대경로로 import 할수 있게 된다.
  • 그럼 아래와 같이 절대경로로 깔끔하게 작성할 수 있다.
import styled from 'styled-components';
import { TextField } from '@components/textfield';
 
...
  • 첫 번째로 baseUrl 속성에 기본 경로를 설정해 주고 그 바로 아래에 paths 속성에 절대 경로를 지정하고 싶은 경로들을 지정해 주면 된다. 추가적으로 outDir 도 설정해준다.
{
  "compilerOptions": {
    "baseUrl": "./", // 절대 경로 모듈이 아닌, 모듈이 기본적으로 위치한 디렉토리 설정
    "paths": { // 'baseUrl'을 기준으로 상대 위치로 가져오기를 다시 매핑하는 항목 설정
      "@components/*": [
        "src/components/*" // import {} from '@components/파일' 할때 어느 경로로 찾아들어갈지 paths 설정
      ],
      "@utils/*": [
        "src/utils/*"
      ],
    },
    "outDir": "./dist", // 컴파일할때 js 파일 위치 경로 지정
  },
}
  • 그러나 실제 ts-node를 이용해 소스 파일을 실행해보면 오류가 난다. 왜냐하면 tsconfig.json 설정은 경로 alias만 준것이지 실제 경로를 바꾼게 아니기 때문이다.

  • 따라서 별도로 tsconfig-pathstsc-alias 라는 모듈이 설치해주어야 한다.

    • tsconfig-paths : tsconfig.json 내에 baseurl 이나 paths필드에 명시된 모듈을 실제로 호출하게 도와주는 라이브러리
    • tsc-alias : js 파일로 컴파일되면 baseurl 이나 paths 필드로 명시된 경로가 그대로 트랜스파일링 되서 js 모듈을 인식할수 없는 현상이 일어나게 되는데, 이 패키지를 이용하면 컴파일된 경로를 상대경로로 바꿔서 해결이 가능하다.
    • > npm i -D tsconfig-paths tsc-alias
    • 그리고 tsconfig.json 파일에서 전역 속성으로 다음과 같이 추가 설정을 해준다.
      {
        "compilerOptions": {
          "baseUrl": "./"
          "path": ...
        },
    
        // 전역 속성으로 추가해준다.
        "ts-node": {
          "require": ["tsconfig-paths/register"]
        }
      }

    조심해야 할점은, @로 시작하는 라이브러리를 npm을 통해 받아서 사용할때 alias 명칭과 중복되지 않게 등록해야 한다.

  • 그리고 ts-node index.ts 명령어를 실행해보면, @경로를 잘 찾아들어가는 걸 확인 할 수 있다.

    • 배포환경의 빌드 같은 경우, 컴파일 명령어를 다음과 같이 하면 된다.
    > tsc && tsc-alias
    • package.json의 script도 설정해주면 좋다.
      "scripts": {
        "build": "tsc --project tsconfig.json && npx tsc-alias -p tsconfig.json",
      }

3.1.2.4 types, typeRoots

  • 타입스크립트 설정 파일은 기본적으로 node_modules를 제외하지만, 라이브러리의 타입을 정의해놓는 @types 폴더는 컴파일에 자동으로 경로에 포함된다.
└─ node_modules
   ├─ @types => 컴파일에 포함
   ├─ lodash => 컴파일에서 제외
  • 여기서 만약 @types의 기본 경로를 변경하고 싶다면 아래와 같이 지정할 수 있다.
"compilerOptions": {
	"typeRoots": ["./my-types"], // 컴파일 목록에 자동으로 포함시킬 패키지들의 기준 디렉토리
	// .d.ts 파일을 읽을 폴더를 node_modules/@types에서 node_modules/my-types로 변경

	"types": ["node", "jest", "express"], // typeRoots 디렉토리 내에 존재하는 패키지들 중 어떤 패키지들을 컴파일 목록에 포함시킬지
	// 만약 types가 지정되어 있지 않다면 typeRoots에 지정된 경로의 패키지들은 전부 컴파일 목록에 자동으로 포함
}

3.1.2.5 resolveJsonModule

  • 확장자가 .json인 모듈의 import를 허용하는 설정이다.

  • 생각해 보면 Node.js 자바스크립트 프로젝트에서 json 설정 파일을 import해서 자주 사용해온걸 떠올릴 것이다.

  • 타입스크립트도 가능할 것이라 생각하지만, json의 프로퍼티들 모두 타입을 지정해야 사용이 가능하다.

  • 이 옵션은 json의 타입을 자동으로 설정해줘서 따로 변환 작업없이 타입스크립트에서 json 파일 데이터들을 곧바로 사용할 수 있도록 해준다.

    • 예를 들어 다음과 같은 json 데이터가 있다고 하자.
    {
     "name":"홍길동",
     "age": 54,
     "height": 170,
     "married": false
    }
    • 원래라면 이렇게 ts 파일에서 사용할수 없게 막혀있다.
      • import settings from "./test.json" // ./test.json 모듈을 찾을 수 없습니다.
    • resolveJsonModule 옵션을 true로 설정해주면, 다음과 같이 자동으로 타입이 매핑되어 사용이 가능해진다.
      "compilerOptions": {
          "resolveJsonModule": true, // ts 파일에서 json imoprt 허용
      }
    		// .josn
    		const s: {
    			"name":"홍길동",
    			"age": 54,
    			"height": 170,
    			"married": false
    		}
    	
    		// .ts
    		import settings from "./test.json"
    
    		...
      
    		const s = settings;
    		console.log(s.name);  // 홍길동

3.1.3 Interop Constraints 옵션

3.1.3.1 esModuleInterop

  • 라이브러리 중에서는 amd(웹) 방식을 전제로 구현된 라이브러리가 있는데 commonjs 방식으로 동작하는 TS에서는 혼란을 줄 수 있다.
  • 상호 운용적(interoperable)으로 사용하기 위해서는 가능한 true로 지정해 놓고 타입스크립트 코딩을 하는것을 권한다.
"compilerOptions": {
	"esModuleInterop": true, /* 모든 가져오기에 대한 네임스페이스 객체 생성을 통해 CommonJS와 ES 모듈 간의 상호 운용성을 제공 */
}
// esModuleInterop: true일 경우 가능함
import React from "react";
 
// false인 경우 다음과 같이 import 해야 함
import * from React from "react";

3.1.3.2 forceConsistentCasingInFileNames

  • 파일의 이름을 대소문자 판별하게 하는 옵션이다.
  • 프로그래밍 세계에선 같은 알파벳이라도 대소문자를 모두 구분하기 때문에 이 옵션은 가능한 true로 해놓고 사용하기를 권장한다.

3.1.4 JavaScript Support 옵션

3.1.4.1 allowJs

  • TypeScript 프로젝트에서 JavaScript 파일도 사용할 수 있도록 하는 설정이다.
  • allowJs: true이면 JavaScript 파일들도 타입스크립트 프로젝트에서 import 될 수 있다.
  • 기본적으로 타입스크립트는 .js 확장자를 허용하지 않는다.
  • 그래서 만일 자바스크립트를 타입스크립트로 바꾸는 프로젝트가 진행중이라면 곤란함을 겪게 된다.
  • 따라서 이 속성은 JavaScript 프로젝트를 TypeScript 프로젝트로 바꾸려 할 때 점진적으로 변환하기 위한 용도로 사용된다.
"compilerOptions": {
	"allowJs": true,
}

3.1.4.2 checkJs

  • ts 파일 뿐만 아니라, js 파일에 있는 에러도 보고하라는 옵션이다.
  • 보통 allowJS 속성과 함께 사용
"compilerOptions": {
    "allowJs": true, // js 파일들 ts에서 import해서 쓸 수 있는지 
    "checkJs": true, // 일반 js 파일에서도 에러체크 여부 
}

3.1.5 Emit 옵션

3.1.5.1 outFile

  • 일반적인 형태로는 하나의 파일로 만들수 없지만, 번들러 형태로 지원하여 하나로 만든다.
  • 단, 모듈이 시스템 혹은 amd와 같은 형태로 지원되어야 파일을 하나로 만들수 있어서, 차라리 따로 웹팩을 사용하지 이 기능을 이용하지는 않아 중요도가 낮은 옵션이다.

3.1.5.2 outDir

  • 기본적으로 컴파일을 진행하면 .ts와 같은 경로에 .js 결과물을 생성하는데,
  • outDir 옵션으로 경로를 수정하여 컴파일된 js 파일들을 담을 폴더를 지정해줄 수 있다.
"compilerOptions": {
	"outDir": "./dist"
}

3.1.5.3 noEmit

  • 타입스크립트를 컴파일하면, JavaScript 변환 파일을 만들어 내지 않도록 하는 설정이다.
  • 이는 곧 타입스크립트를 에디터 통합 기능을 제공하기 위한 도구 혹은 소스 코드 타입 체커로만 사용하게 되는 꼴이 된다.
  • 만일 Babel이나 swc와 같은 또 다른 도구가 변환하는 작업을 대신 담당하는 경우 사용되는 옵션이라고 이해하면 된다.
"compilerOptions": {
    "noEmit": true,
}

3.1.5.4 sourceMap

  • 컴파일된 파일 디렉터리에 .js.map 파일이 만들어진다.
  • 이 소스맵 파일은 변환된 js코드가 ts의 어디에 해당하는 지를 알려준다. 디버깅 작업에 매우 유용하다.
"compilerOptions": {
    "sourceMap": true, /* 소스맵 '.map' 파일 생성 설정 */
}
  • 실제로 타입스크립트 프로젝트를 배포하고, 브라우저에서 개발자모드를 이용해 source 탭에 보면, 브라우저는 js만 인식하지만 매핑 파일에 의해 ts 파일을 인식하는걸 볼 수 있다.

3.1.5.5 downlevelIteration

  • 타입스크립트에서 제너레이터 function* {}, yeild... 를 사용하기 위한 옵션
  • 코드를 이전 버전의 js로 컴파일하고 for loop로 작업하면 컴파일이 제대로 작동하지 않을 수 있어, 이 속성을 설정을 해놓으면 정확도가 올라가지만 js코드량이 늘어나기 때문에, 의도한대로 loop가 작동하지 않을 때만 사용하길 권한다.
"compilerOptions": {
    "downlevelIteration": true, //* 'ES5' 혹은 'ES3' 타겟 설정 시 Iterables 'for-of', 'spread', 'destructuring' 완벽 지원 설정 */
}

3.1.5.6 removeComments

  • 컴파일 시 타입스크립트 소스의 주석을 모두 제거하는 것을 설정한다.
"compilerOptions": {
    removeComments": true, // true면 컴파일된 js에 기존의 주석을 모두 제거
}

3.1.5.7 noEmitOnError

  • 원래는 타입스크립트에 구문 에러가 발생하더라도, 컴파일하면 js파일을 생성하는데, 위 설정을 true로 설정하면 에러가 발생한 ts파일은 컴파일을 막는다.
"compilerOptions": {
    noEmitOnError": true, // 컴파일 에러가 있으면 js 컴파일 하지 않음
}

3.1.5.8 declaration

  • 이 옵션을 true로 하면 TS파일을 JS로 컴파일하는 과정에서 JS파일과 함께 d.ts 파일이 생성되게 한다.
  • 객체랑 함수를 쓰다보면 타입을 커스텀하는 경우가 온다. 이때 타입들을 ts파일에 넣어도 되지만 용도가 다르기때문에 분리하는 것이 좋다.
  • 그럴때 d.ts파일을 만들어 따로 타입만을 관리하는데 이럴때 사용되는 옵션이다.
"compilerOptions": {
    "declaration": true, //컴파일시 .d.ts 파일도 자동으로 함께생성 (현재쓰는 모든 타입이 정의된 파일)
}

3.1.6 Type Checking 옵션

3.1.6.1 strict

  • 타입스크립트의 각종 타입 체킹 동작을 전부 활성화한다.
  • 사실상 이 옵션을 쓰지않는것은 곧 타입스크립트를 쓰지 않는 다는 것과 같다. 따라서 기본으로 활성화 되어 있다.
"compilerOptions": {
    "strict": true /* 모든 엄격한 유형 검사 옵션 활성화 */
}
  • 이 프로퍼티를 true로 지정하면 strict mode family 프로퍼티들을 전부 true로 지정하는 것과 동일하다.
  • 만일 사소한 부분에도 너무 지나치게 빨간줄을 긋는게 불편하다면, 선택적으로 몇 개의 strict mode family 프로퍼티를 false로 지정하는 식으로 설정하면 된다.
  • strict mode family 프로퍼티들
    • alwaysStrict 프로퍼티
    • strictNullChecks 프로퍼티
    • strictBindCallApply 프로퍼티
    • strictFunctionTypes 프로퍼티
    • strictPropertyInitialization 프로퍼티
    • noImplicitAny 프로퍼티
    • noImplicitThis 프로퍼티

3.1.6.2 noImplicitAny

  • 명시적이지 않은 any 타입이 지정될 경우 표현식과 선언에 사용하면 에러 발생 시킨다.
  • 예를들어 타입스크립트가 추론을 실패해서 any로 지정되면 빨간줄이 뜨게 되는데, 이때 직접 any라고 지정해야 빨간줄이 사라진다.
  • 위의 strict 옵션을 true로 하면 noImplicitAny 옵션도 자동으로 true가 되서 나타나는 현상인데, 이때 이 옵션을 false로 지정하면 아래와 같이 any 타입을 명시적으로 지정 안해도 오류가 사라지게 된다.
"compilerOptions": {
    "strict": true,
    "noImplicitAny": false /* 명시적이지 않은 'any' 유형으로 표현식 및 선언 사용 시 오류 발생 */
}
function methodDecorator() {
   console.log('method');
   return function (target, property, descriptor) {}; // noImplicitAny: false로 하면, 명시적 any를 안써도 에러가 안난다.
}

3.1.6.3 suppressImplicitAnyIndexErrors

  • nolmplicitAny를 사용할 때 인덱스 객체에 인덱스 시그니처가 없는 경우 오류가 발생하는 것을 예외 처리 해준다.
  • 예를들어 suppressImplicitAnyindexErrors옵션을 true로 설정해주면, person 객체에 age 라는 프로퍼티가 없어도 person['age'] 를 에러를 내주지 않는다.
"compilerOptions": {
    "strict": true,
    "suppressImplicitAnyIndexErrors": true,
}
const person = {
   name: '홍길동',
};

console.log(person['age']); // suppressImplicitAnyIndexErrors: true로 하면 그냥 undefined를 출력한다

3.1.6.4 noImplicitThis

  • 암시적 any 유형이 있는 this 표현식에서 오류를 발생시킨다.
  • 본래라면 명시적 this를 통해 오류를 해결하지만, this에 any가 오는걸 허용한다면 이 옵션을 false로 지정해주어 빨간줄을 지울 수 있다.
"compilerOptions": {
    "strict": true,
    "noImplicitThis": false, /* 명시적이지 않은 'any'유형으로 'this' 표현식 사용 시 오류 발생 */
}
class Rectangle {
   width: number;
   height: number;

   constructor(width: number, height: number) {
      this.width = width;
      this.height = height;
   }

   getAreaFunction() {
      return function () {
         return this.width * this.height; // 원래는 명시적 this를 써야하지만, "noImplicitThis": false 하면 안써줘도 된다.
      };
   }
}

3.1.6.5 strictNullChecks

  • null및 undefined 값에 대한 유형을 조정하는 옵션이다.
  • strickNullChecks를 적용하면, 모든 타입은 null, undefined값을 가질 수 없고 가지려면 union type으로 직접 명시해야 한다.
  • 단, 기본적으로 any에 null, undefined할당 가능하며 void에는 undefined 할당 가능하다.
  • 함수를 선언할 때부터 매개변수와 리턴 값에 정확한 타입을 지정할 수 있는 효과가 있다.
  • 만일 strickNullChecks를 적용하지 않을 경우 모든 타입은 null, undefined값을 할당 가능해진다.
"compilerOptions": {
    "strict": true,
    "strictNullChecks": false, /* 엄격한 null 검사 사용 */
}
  • 활성화 권장

3.1.6.6 strictFunctionTypes

  • 타입스크립트는 기본적으로 공변적(covariant)인 규칙을 따르지만, 함수의 매개변수 만이 이변량(bivariant)의 구조를 가진다.
  • 따라서 매개변수 타입이 달라도 막 대입할수 있는 현상이 일어나게 되는데, 이를 반공변적(contravariant)으로 설정해주어 이변성의 오류를 해결한다.
  • 하지만 자바스크립트에선 서로의 콜백을 함수에 인자로 전달하는 일이 빈번하기 때문에 오히려 이런 옵션이 활성화 되있는게 거슬릴수 있는데, 이 옵션을 false로 하면 반공병성을 끌수 있다.
"compilerOptions": {
    "strict": true,
    "strictFunctionTypes": false, /* 엄격한 함수 유형 검사 사용 */
}
function fn(x: string) {
   console.log('Hello, ' + x.toLowerCase());
}

type StringOrNumberFunc = (ns: string | number) => void;

// Unsafe assignment
let func: StringOrNumberFunc = fn; // 대입이 가능해진다.

func(10); // Unsafe call - will crash

3.1.6.7 strictPropertyInitialization

  • 정의되지 않은 클래스의 속성이 생성자에서 초기화되었는지 확인한다.
  • 예를 들어 UserAccount 클래스의 constructor에서는 name 프로퍼티만 초기화해주고 email 프로퍼티는 선언만 하였는데, 이때 너무 강하게 타입 체킹 하는 느낌이 든다면, 이 옵션을 false로 줘서 빨간줄을 해결할 수 있다.
"compilerOptions": {
    "strict": true,
    "strictPropertyInitialization": false, /* 클래스에서 속성 초기화 엄격 검사 사용 */
}
class UserAccount {
   name: string; 
   accountType = 'user'; 
   address: string | undefined; 

   email: string; // strictPropertyInitialization: false로 하면 빨간줄이 사라진다.

   constructor(name: string) {
      this.name = name;
   }
}
  • tsconfig를 수정하는게 마음에 안들면, non-null 단언 연산자를 이용해도 해결 할수 있다.
email!: string; // 어디선가 할당될 것이므로 에러를 무시하라는 의미

3.1.6.8 strictBindCallApply

  • function의 내장 함수인 bind, call, apply를 사용할 때 더욱 엄격하게 검사하는 옵션이다.
"compilerOptions": {
    "strict": true,
    "strictBindCallApply": false, /* 엄격한 'bind', 'call', 'apply' 함수 메서드 사용 */
}
function fn(x: string) {
   return parseInt(x);
}

const n1 = fn.call(undefined, '10');

const n2 = fn.call(undefined, false); // strictBindCallApply: false 로 하면 아무거나 넣을 수 있다.

3.1.6.9 alwaysStrict

  • 컴파일된 자바스크립트 파일에 "use strict" 모드를 사용하도록 명시한다.
  • strict 옵션이 활성화 되어있을경우 기본적으로 이 옵션도 활성화 되며, 만일 이 옵션을 false로 지정하면 컴파일된 자바스크립트 파일에선 strict mode를 쓰지 않게 된다.
"compilerOptions": {
    "strict": true,
    "alwaysStrict": false, /* 엄격모드에서 구문 분석 후, 각 소스 파일에 "use strict" 코드를 출력 */
}

3.1.6.10 strict 속성에 국한되지 않은 독립적인 추가 검사 옵션

noUnusedLocals

  • 쓰지않는 지역변수 있으면 에러내기

noUnusedParameters

  • 쓰지않는 파라미터 있으면 에러내기

noImplicitReturns

  • 함수에서 return 빼먹으면 에러내기

noFallthroughCasesInSwitch

  • switch문 이상하면 에러내기
  • 예를들어 switch 문에서 비어 있지 않은 Case라면 반드시 break 문이나 return 문으로 해당 Case를 종료시키도록 에러를 내준다.
  • 이를 통해 의도치 않은 Fallthrough Case에 의한 버그를 예방할 수 있다.

3.1.7 Completeness 옵션

3.1.7.1 skipLibCheck

  • 타입 체킹을 스킵하도록 하는 설정이다.
  • 타입스크립트에 타입 체킹을 안하면 무슨 의미가 있겠냐 싶지만, 만일 프로젝트의 규모가 크면 라이브러리의 선언 파일들이 매우 방대할 텐데, 그것들을 매번 다시 체크하는 것은 상당한 시간이 소모가 된다.
  • 그래서 이 옵션을 true로 지정하여 선언 파일들의 타입 체크를 생략하도록 하여 컴파일 시간을 줄여주도록 하기 위한 속성이다.
"compilerOptions": {
    "skipLibCheck": true, /* 선언 파일 유형 검사 스킵 */
}

3.2 include & exclude

  • include & exclude는 컴파일할 경로, 파일들과 혹은 컴파일 제외할 대상을 경로와 파일들을 배열로 정할 수 있다.

  • include 컴파일 과정에서 포함할 파일

    • includefiles 속성과는 달리 exclude보다 약해 include에 명시되어 있어도 exclude에 의해 제외된다.
    {
      "include": ["src/**/*"] // src 디렉터리와 src의 하위 디렉터리에 있는 모든 파일을 컴파일 대상으로 포함한다는 의미
     }
  • exclude 빌드(컴파일) 제외 항목을 기입

    • exclude는 아무 설정을 하지 않아도 node_modules, bower_components, jspm_packages, outDir를 기본으로 제외한다.
      {
        "exclude": ["node_modules"] 
      }
  • include, exclude의 편리한 점은, include* 만 쓰고 확장자를 적지 않아도 자동으로 .ts .tsx. .d.ts 만 트랜스파일한다는 것이다.
    (allowJS: true로 지정되어 있다면 .js, .jsx 확장자까지 지원이 된다.)

  • 자주 사용되는 include & exclude의 glob 패턴
    • 와일드카드 문자 패턴
    • * : 해당 디렉토리의 모든 파일 검색
    • ? : 해당 디렉토리 안에 파일의 이름 중 한 글자라도 맞으면 해당
    • ** : 하위 디렉토리를 재귀적으로 접근(하위 디렉토리의 하위 디렉토리가 존재하는 경우 반복해서 접근)

      Glob 패턴
      특정 규칙을 가진 파일 명 또는 디렉터리 명을 대상으로 검색하는 기술
      위 와일드카드에 해당하는 파일의 확장자는 js jsx ts tsx .d.ts

3.3 files

  • 변환 대상 개별 파일의 경로를 설정 파일에 정의 (files는 개별 파일, include는 폴더채)
  • files 전역 속성은 컴파일할 대상 개별 파일들을 담은 리스트
  • 프로그램에 포함하고 싶은 파일들의 목록을 지정한다. (파일 확장자까지 정확히 작성해줘야 한다)
  • files는 exclude보다 우선순위가 높아서 특정 파일을 지정해서 컴파일 할때 쓰인다.
{
  "files": ["app.ts", "./utils/math.ts"]
}

3.4 extends

  • extends는 다른 tsconfig 설정들을 가져와 쓸때 사용되는 옵션이다.
  • 특정 타입스크립트 설정 파일에서 다른 타입스크립트 설정의 내용을 가져와 추가할 수 있다.
  • 예를들어 config/base.json 파일의 속성 설정을 현 tsconfig.json 파일에 포맷이 맞으면 가져올 수 있다.
  • 다른 타입스크립트 설정의 내용을 가져와 덮어씀
// config/base.json
{
  "compilerOptions": {
    "noImplicitAny": true
  }
}



// tsconfig.json
{
  "extends": "./config/base"
}

3.5 tsconfig.json setting

{
  "compilerOptions": {
    "module": "commonjs",
    "esModuleInterop": true,
    "target": "ES5",
    "moduleResolution": "node",
    "outDir": "dist",
    "baseUrl": ".",
    "sourceMap": true,
    "downlevelIteration": true,
    "noImplicitAny": false,
    "paths": { "*": ["node_modules"] }
  },
  "include": ["src/**/*"] // ./src와 ./src/utils 디렉터리에 프로젝트의 모든 타입스크립트 소스 파일이 있다는 뜻
}

4. source file 생성

include 옵션에서 ./src와 ./src/utils 디렉터리에 프로젝트의 모든 타입스크립트 소스 파일 설정

> mkdir -p src/utils

> touch src/index.ts src/utils/makePerson.ts

-p (--parents) 상위 경로도 함께 생성

// src/utils/makePerson.ts

export function makePerson(name: string, age: number) {
  return { name: name, age: age };
}

export function testMakePerson() {
  console.log(makePerson("Son", 30), makePerson("Kane", 28));
}
// src/index.ts
import { testMakePerson } from "./utils/makePerson";
testMakePerson();

5. package.json 수정

// 수정 전

{
  ...

  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },

  ...

}
  • 타입스크립트 프로젝트를 개발할 때는 ts-node를 사용하지만, 개발이 완료되면 타입스크립트 소스를 ES5 자바스크립트 코드로 변환해 Node.js로 실행해야한다.
  • 이를 위해 아래와 같이 수정한다.
// 수정 후

{
  ...

  "main": "src/index.js",
  "scripts": {
    "dev": "ts-node src",
    "bulid": "tsc && node dist"
  },

  ...

}
  • dev 명령은 개발 중에 src 디렉터리에 있는 index.ts 파일을 샐힝하는 용도로 사용하며,
  • build 명령은 개발이 완료된 후 프로그램을 배포하기 위해 dist 디렉터리에 ES5 자바스크립트 파일을 만들때 사용

6. 컴파일 & run

> npm run dev

> 01@1.0.0 dev
> ts-node src ## dev 명령에 정의된 명렁

{ name: 'Son', age: 30 } { name: 'Kane', age: 28 }  ## 코드 실행 결과

7. build

> npm run build

> 01@1.0.0 build
> tsc && node dist ## dev 명령에 정의된 명렁

{ name: 'Son', age: 30 } { name: 'Kane', age: 28 }  ## 코드 실행 결과
  • dist/index.js, dist/utils/makePerson.js로 컴파일 됨

0개의 댓글