참고자료
- https://velog.io/@jejualrock/%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EC%84%A4%EC%A0%95
- [inpa dev] 타입스크립트 컴파일 설정 - tsconfig 옵션 총정리
- 토스트 타입스크립트에서의 모듈 설명글 : https://ui.toast.com/weekly-pick/ko_20190418
- https://codingapple.com/unit/typescript-tsconfig-json/
- 공식 문서 : https://www.typescriptlang.org/docs/handbook/tsconfig-json.html
- { tsconfig.json } 제대로 알고 사용하기
> tsc --init
을 치면 타입스크립트 설정 파일인 tsconfig.json 파일이 생성된다. 많은 설정들이 주석처리된 채로 들어가 있다.
{
"compilerOptions":{
"module": "CommonJS" //"ESNext"
},
}
컴파일한 결과물인 js파일을 CommonJS모듈을 쓰도록 컴파일할 건지,
ES 모듈을 쓰도록 컴파일할 건지를 지정하는 옵션이다.
컴파일 결과로 만들어낼 자바스크립트의 버전을 지정.
값에 e만 쳐도 넣을 수 있는 값 예시들이 뜬다.
ESNext는 최신 문법을 의미한다.
만약에 화살표함수를 작성한 후에 타겟을 화살표함수를 지원하지 않는 ES5로 설정해두고 컴파일을 하면 함수표현식으로 변경되어있는 것을 볼 수 있다.
포함할 타입들을 지정한다.
node_modules 폴더를 컴파일에서 제외하지만 설치한 패키지들에서 쓰는 타입들은 이 옵션을 굳이 명시하지 않아도 기본적으로 컴파일에 포함된다.
"typeRoots": ["node_modules/@types"]
즉, 이 옵션이 기본으로 되어 있는 것이라 보면된다. 실제로
node_modules/@types 경로를 가보면 설치한 패키지별로 index.d.ts 파일을 갖고 있다.
.d.ts라는 확장자는 타입을 지정한 파일들을 의미하는데 d는 declare의 약자다.
평소에 타입을 지정할 때는 굳이 .d를 안붙여도 되긴한다는데 약속인 듯 하다.
이 옵션을 명시해줘야 하는 경우는 기본적인 저 경로 말고도 포함시킬 경로가 있을 경우이다.
"typeRoots": ["node_modules/@types", "src/types"]
다른 경로를 추가할 때에는 기본으로 포함되어있던 저 node_modules/@types도 명시해주어야 한다.
import나 require의 경로 작성 시에 별칭을 부여해서 경로 작성을 쓰기 쉽게 해준다.
같은 파일을 다른 경로에서 import할 때마다 .. 갯수를 변경해야할 때가 있는데 그런 불편을 줄여준다.
{
"compilerOptions": {
"baseUrl": "./",
"paths": { // 'baseUrl'을 기준으로 상대 위치로 가져오기를 다시 매핑하는 항목 설정
"@middlewares/*": ["src/middlewares/*"]
},
},
}
하지만 여기서 설정한 별칭을 실제로 import나 require 구문의 path에 사용했다면
컴파일된 js파일에서는 그것을 인식하지 못해서 에러가 날 것이다.
다음의 두 패키지들을 설치하고 스크립트에 반영해주어야 한다.
tsconfig.json 파일은 컴파일할 때만 참고되는 파일이기 때문에 js파일에는 그 path 별칭들이 적용되지 않는다.
tsc-alias 패키지를 깔고 컴파일 시에 옵션으로 넣어주면 해당 별칭들을 실제 경로로 바꿔서 컴파일을 해준다.
그런 다음 다음과 같이 tsc-alias를 포함한 스크립트로 빌드 스크립트를 변경해 준다.
"scripts": {
"build": "tsc --project tsconfig.json && tsc-alias -p tsconfig.json",
}
================ OR ===================
"scripts": {
"build": "tsc && tsc-alias",
"build:watch": "tsc && (concurrently \"tsc -w\" \"tsc-alias -w\")"
}
위의 tsc-alias과 같은 경로 별칭 문제를 해결할 때쓰는 것인데 다른 점은
ts-node 명령어로 실행시킬 때 이 문제를 해결 시키는 패키지라는 점이다.
설치 후에 다음과 같이 "-r tsconfig-paths/register"를 스크립트에 추가시켜주면 된다.
ts-node -r tsconfig-paths/register main.ts
타입검사를 얼마나 엄격하게 할지 지정. 지정하지 않으면 기본이 true이다.
이것을 true로 설정하면 엄격하게 타입 검사를 하고 false로 하면 최소한의 타입 검사만을 하게 된다.
이 옵션에는 몇개의 하위 옵션들이 있는데 그것들을 개별 설정하고자 한다면 그것들을 따로 명시해주어도 된다.
보통 JavaScript에서 typescript로 마이그레이션을 시작할 때는 일단 끄고 마이그레이션 작업을 먼저 진행하고 이 하위 옵션들을 하나씩 켜가면서 수정해 나간다.
null 및 undefined 값에 대한 엄격한 타입 검사를 수행합니다.
변수 또는 속성이 null 또는 undefined 값을 가질 가능성이 있는 경우, 타입 에러를 발생시킵니다.
암묵적인 any 타입을 허용하지 않습니다.
모든 변수와 함수 파라미터에 명시적인 타입 어노테이션을 제공하거나, 타입 추론을 통해 타입을 결정하도록 요구합니다.
함수 타입의 호환성 검사를 강화합니다.
함수 타입의 매개변수와 반환 값에 대한 타입 호환성을 더 엄격하게 검사합니다.
클래스 프로퍼티의 초기화를 강제화합니다.
클래스 내부에서 정의한 프로퍼티가 생성자나 프로퍼티 초기화자를 통해 초기화되지 않으면 타입 에러를 발생시킵니다.
함수의 bind, call, apply 메서드의 호출을 더 엄격하게 검사합니다.
이 옵션을 활성화하면 함수 호출 시 메서드와 함수의 타입 호환성 검사가 더 엄격해집니다.
nullish coalescing 연산자(??)를 사용할 때의 타입 검사를 활성화합니다.
이 옵션을 사용하면 ?? 연산자를 사용할 때 null 또는 undefined가 있는 경우에도 타입 에러를 발생시킵니다.
클래스의 속성 순서를 강제화합니다.
이 옵션을 사용하면 클래스 내의 프로퍼티 선언 순서를 엄격하게 지켜야 합니다.
true로 하면 암묵적인 any에 빨간줄이 뜨게 된다.
타입 추론에 실패한 경우에 암묵적으로 any 타입이 되게 되는데
실제 적절한 type을 넣어주거나, 그래도 any로 써야겠다면 any를 명시해주면 해결된다.
{
"compilerOptions": {
// strict나 noImplicitAny를 명시하지 않아도 noImplicitAny는 true인 상태
"suppressImplicitAnyIndexErrors": true
}
}
noImplicitAny가 true인 상황에만 유효한 옵션으로,
암묵적인 any 중에서도 다음과 같은 경우에는 오류를 내지 않도록 한다.
const obj = {
name: 'John',
age: 30,
};
const propertyName = 'name';
const value = obj[propertyName];
변수를 통해 객체의 속성에 동적으로 접근하는 경우에 타입스크립트는 이를 any로 인식한다고 한다.
noImplicitAny 가 true더라도 suppressImplicitAnyIndexErrors가 true이면 이러한 경우에 에러를 내지 않는다.
include : 컴파일할 파일의 범위를 지정
ourDir : 컴파일 결과물 생성 위치 지정
{
"compilerOptions":{
"target":"ESNext",
"module":"CommonJS",
"outDir" : "dist"
},
"include" : ["src"]
}
보통 컴파일할 파일들을 ./src 폴더 안에 몰아넣고 개발 후 이와같은 설정으로 많이 쓴다.
ourDir에 dist라고 보통 쓰는데 distribution 즉 배포의 의미를 가진다.
컴파일할 파일들의 개별 목록을 지정하는 속성
"files": ["src/main.ts", "src/utils.ts"],
include와 비슷하게 컴파일할 파일을 개별로 지정하는 files라는 옵션도 있는데 include를 쓰면 굳이 안써도 된다. 글로벌타입을 지정하기 위해 .d.ts파일을 사용할 때에도 그 파일이 include 안에만 들어가 있으면 굳이 따로 명시해서 포함시켜줄 필요는 없다.
대신에 exclude보다 우선순위가 높아서 exclude로 제외한 폴더 중에서 포함시킬 파일만을 지정할 때는 쓴다.
컴파일에서 제외할 파일 경로 지정
인클루드보다 우선순위가 높고, files보단 낮다.