TypeScript: TypeScript Compiler Ep.2 compileOptions

compileOptions - typeRoots, types


"typeRoots": {
	"description": "Specify multiple folders that act like `./node_modules/@types`.",
	"type": "array",
	"uniqueItems": true,
	"items": {
		"type": "string"
	},
	"markdownDescription": "Specify multiple folders that act like `./node_modules/@types`."
}
"types": {
	"description": "Specify type package names to be included without being referenced in a source file.",
	"type": "array",
	"uniqueItems": true,
	"items": {
		"type": "string"
	},
	"markdownDescription": "Specify type package names to be included without being referenced in a source file."
}

@types

  • TypeScript 2.0부터 사용 가능해진 내장 type definition 시스템이다.
    이전에는 내장이 아닌 서드파티 type definition이었다. 이제는 내장으로 통합.
  • 아무 설정을 하지 않으면
    • node_modules/@types 라는 모든 경로를 찾아서 사용한다.
  • typeRoots를 사용하면
    • 배열 안에 들어있는 경로들 아래에서만 가져온다. 나는 node_modules 안의 @types 도 쓰겠지만 내 프로젝트 안의 @types도 쓸거라면 typeRoots를 지정해 주면 편하게 사용할 수 있다.
  • types를 사용하면
    • 배열 안의 모듈 혹은 ./node_modules/@types/ 안의 모듈 이름에서 찾아온다.
    • 빈 배열을 넣는다는 건 이 시스템을 이용하지 않겠다는 것이다.
  • typeRoots 와 types를 같이 사용하지 않는다.

compileOptions - target 과 lib


"target": {
	"description": "Set the JavaScript language version for emitted JavaScript and include compatible library declarations.",
	"type": "string",
	"default": "ES3",
	"anyOf": [
		{
			"enum": [
				"ES3",
				"ES5",
				"ES6",
				"ES2015",
				"ES2016",
				"ES2017",
				"ES2018",
				"ES2019",
				"ES2020",
				"ES2021",
				"ES2022",
				"ESNext"
			]
		},
		{
			"pattern": "^([Ee][Ss]([356]|(20(1[56789]|2[012]))|[Nn][Ee][Xx][Tt]))$"
		}
	],
	"markdownDescription": "Set the JavaScript language version for emitted JavaScript and include compatible library declarations."
}

"lib": {
	"description": "Specify a set of bundled library declaration files that describe the target runtime environment.",
	"type": "array",
	"uniqueItems": true,
	"items": {
		"type": "string",
		"anyOf": [
			{ ... }
		]
	},
	"markdownDescription": "Specify a set of bundled library declaration files that describe the target runtime environment."
}

target

  • 빌드의 결과물을 어떤 버전으로 할 것인지 설정한다.
  • 지정은 안하면 es3이다.

lib

  • 기본 type definition 라이브러리를 어떤 것을 사용할 것인지 결정한다.
  • lib를 지정하지 않을 때, (target에 따라 자동으로 설정됨)
    • target이 ‘es3’이고, default로 lib.d.ts 를 사용한다.
    • target이 ‘es5’이면, default로 dom, es5, scripthost 를 사용한다.
    • target이 ‘es6’이면, default로 dom, es6, dom.iterable, scripthost 를 사용한다.
  • lib를 지정하면 그 lib 배열로만 라이브러리를 사용한다.
    • 빈 [ ] (배열) ⇒ error! ‘no definition found ~~’

compileOptions - outDir, outFile, rootDir


"outFile": {
	"description": "Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output.",
	"type": "string",
	"markdownDescription": "Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output."
}

"outDir": {
	"description": "Specify an output folder for all emitted files.",
	"type": "string",
	"markdownDescription": "Specify an output folder for all emitted files."
}

"rootDirs": {
	"description": "Allow multiple folders to be treated as one when resolving modules.",
	"type": "array",
	"uniqueItems": true,
	"items": {
		"type": "string"
	},
	"markdownDescription": "Allow multiple folders to be treated as one when resolving modules."
}

outFile

단일 파일로 합쳐서 출력한다.

outDir

해당 디렉토리로 결과 구조를 보낸다.

rootDir

입력 파일의 루트 디렉토리 설정으로, –outDir로 결과 디렉토리 구조를 조작할 때 사용됩니다.

  • rootDir 설정했을 때

    파일 구조 설명

    • src/test.ts
    • src/hello.ts
    "rootDir": "./src"
    "outDir": "./dist"
    

    컴파일 시(npx tsc), dist 폴더가 생성되면 해당 폴더 안에 test.js와 hello.js 파일이 생성된다.

  • rootDir 설정하지 않을 때

    파일 구조 설명

    • src/test.ts
    • ./hello.ts
    // "rootDir": "./src"
    "outDir": "./dist"
    

    컴파일 시, dist 폴더가 생성되면서 해당 폴더 안에 src폴더가 만들어진다.

    컴파일 이후, 폴더 구조 설명

    • dist/src/tset.js
    • dist/hello.js

    rootDir을 따로 설정하지 않았기 때문에 루트(시작점)이 해당 폴더(compilation-context, 최상위)가 된 것이다. rootDir을 설정했을 때에는 해당 설정이 루트(시작점)이 된다.

compileOptions - strict


앞으로 작업할때는 strict를 true로 설정하고 작업하는 것이 기본이다.

"strict": {
	"description": "Enable all strict type checking options.",
	"type": "boolean",
	"default": false,
	"markdownDescription": "Enable all strict type checking options."
}

모든 strict type checking option을 모두 키는 것

  • —nolmplicitAny
  • —nolmplicitThis
  • —strictNullChecks
  • —strictFunctionTypes
  • —strictPropertyInitialization
  • —strictBindCallApply
  • —alwaysStrict


  • –nolmplicitAny

    명시적이지 않게 any 타입을 사용하여 표현식과 선언에 사용하면 에러를 발생시킨다. (직접으로 any로 표현하지 않았는데 any로 추론이 되는 것)

    • 타입스크립트가 추론을 실패한 경우(추론 결과가 어떤 것이든 들어올 수 있는 상황) any가 맞으면 any라고 지정하라는 의미를 가지고 있다.
    • 아무것도 쓰지 않으면 에러를 발생시킨다.
    • 해당 오류를 해결하면, 타입 추론이 되었으므로 any라고 지정되어 있지 않은 경우는 any가 아닌 것이다.

    nolmplicitAny를 사용할 때, 인덱스 객체에 인덱스 signature가 없는 경우 오류가 발생하는데 이를 예외처리하는 옵션이 있다.

    obj['foo'] = 10; // Error: Index signature of ~~
    

    obj[’foo’] 로 사용할 때, 인덱스 객체라 판단하여 타입에 인덱스 시그니처가 없는 경우, 에러를 발생시킨다.
    이때, suppressImplictitAntIndexErrors 옵션을 사용하면 해당 경우는 예외로 간주하여 에러를 발생시키지 않는다.

  • –noImplicitThis

    명시적이지 않게 any 타입을 사용하여, this 표현식에 사용하면 에러를 발생시킨다.
    (this에 아무거나 들어올 수 없게 들어올 수 있는 형태를 제한해주는 것이 좋다.)

    • 첫번째 매개변수 자리에 this를 놓고, this에 대한 타입을 어떤 것이라도 표현하지 않으면 nolmplicitAny가 오류를 발생시킨다.
    • JavaScript 에서는 매개변수에 this를 넣으면 이미 예약된 키워드라 SyntaxError를 발생시킨다.
    • call / apply / bind와 같이 this를 대체하여 함수 콜 용도로도 쓰인다.
    • 그래서 this를 any로 명시적으로 지정하는 것이 합리적이다. (단, 구체적인 사용처가 있는 경우 타입을 표현하기도 한다.)
  • –strictNullChecks

    strictNullChecks에서는 null 및 undefined 값이 모든 유형의 도메인에 속하지 않으며, 그 자신을 타입으로 가지거나 any일 경우에만 할당이 가능하다.
    즉, 해당 옵션을 키지 않으면 모든 타입에 null과 undefined가 포함된 상태로 사용하게 되는 것이다.
    한가지 예외는 undeifined에 void 할당이 가능하다.

    • strictNullChecks를 적용하지 않으면,
      • 모든 타입은 null, undefined 값을 가질 수 있다.
      • string으로 타입을 지정해도 null 혹은 undefined 값을 할당할 수 있다. → 엄청 큰 오류
    • strictNullChecks 적용하면,
      • 모든 타입은 null, undefined 값을 가질 수 없고, 가지려면 union type을 이용해서 직접 명시 해야 한다.
      • any 타입은 null과 undifined를 가진다. 예외적으로 void 타입의 경우 undefined를 가진다.
  • –strictFunctionTypes

    함수 타입에 대한 bivariant 매개변수 검사를 비활성화한다.

    ( Animal → Greyhound ) <: (Dog → Dog)

    • 반환 타입은 공변적(covariant)
    • 인자 타입은 반공변적(contravariant)
    • 타입스크립트에서 인자 타입은 공변적이면서, 반공변적이다 → 문제!
    • 해당 문제를 해결하는 옵션이 strictFunctionTypes이다.
    • 옵션을 키면, 에러가 나지 않던 걸 나게 한다.
  • –strictPropertyInitialization

    정의되지 않은 클래스의 속성이 생성자에게 초기화되었는지 확인한다.
    해당 옵션을 사용하려면 —strictNullChecks를 사용하도록 설정해야 한다.

    • constructor에서 초기값을 할당한 경우 ⇒ 정상
    • constructor에서 안하는 경우
      • 보통 다른 함수로 이니셜라이즈 하는 경우 (async 함수)
      • constructor에는 async를 사용할 수 없다.
  • –strictBindCallApply

    bind, call, apply에 대한 더 엄격한 검사 수행을 한다.

    • Function의 내장 함수인 bind, call, apply를 사용할 때 엄격하게 체크하도록 하는 옵션이다.
    • bind는 해당 함수안에서 사용할 this와 인자를 설정해주는 역할을 하고, call과 apply는 this와 인자를 설정한 후 실행까지 한다.
    • call과 apply는 인자를 설정하는 방식에서 차이점이 있다.
      call은 함수의 인자를 여러 인자의 나열로 넣어서 사용하고, apply는 모든 인자를 배열 하나로 넣어서 사용한다.
  • –alwaysStrict

    각 소스파일에 대해 자바스크립트의 strict mode로 코드를 분석하고 “엄격하게 사용”을 해제한다.
    그렇게 하면 syntax에러가 ts error로 나오고, 컴파일된 자바스크립트 파일에 “use strict”가 추가된다.

Comments