8.1 마이그레이션을 해야 하는 이유8.2 마이그레이션 가이드8.2.1 디렉토리 설정하기8.2.2 tsconfig.json 생성과 기본 설정8.2.2.1 tsconfig.json 파일 생성하기8.2.2.2 tsconfig.json 커스터마이징8.2.2.3 include 와 exclude8.2.2.4 compilerOptions8.2.3 에러 방지8.2.3.1 noImplicitReturns 설정하기8.2.3.2 noImplicitAny 설정하기8.2.4 TypeScript 파일로 변환하기8.3 마이그레이션 이후8.3.1 암묵적 타입 추론 금지! noImplicit8.3.1.1 noImplicitAny8.3.1.2 noImplicitReturns8.3.1.3 noImplicitOverride8.3.1.4 noImplicitThis8.3.2 조금 더 엄격하게! strict8.3.2.1 alwaysStrict8.3.2.2 strictNullChecks8.3.3 안 쓰는 건 없애자! noUnused 8.3.3.1 noUnusedLocals8.3.3.2 noUnusedParameters
8.1 마이그레이션을 해야 하는 이유
1장에서 살펴본 바와 같이 타입스크립트는 자바스크립트보다 개선된 언어이다. 새로운 프로젝트를 시작한다면 처음부터 타입스크립트로 작성하면 되지만, 이미 자바스크립트로 작성되어 있는 프로젝트는 규모가 매우 클 수 있기 때문에 점진적으로 타입스크립트로 전환하는 과정이 필요하다.
규모가 큰 프로젝트를 타입스크립트로 마이그레이션 하는 과정은 많은 시간을 소모할 수 있으나, 결과적으로 자바스크립트에 타입을 추가해 줌으로써 코드의 퀄리티와 가독성을 높일 수 있고 프로젝트 과정에서 발생할 수 있는 런타임 에러들(예를 들어 동일 연산자의 인수 강제 변환, 존재하지 않는 프로퍼티의 접근 허용 등으로 인한 에러)을 방지할 수 있다. 프로젝트의 유지 및 보수에 많은 이점이 된다.
현재 구글, 마이크로소프트, 메타(구 페이스북)와 같은 회사들은 타입스크립트를 사용하고 있다. 또한, 자바스크립트 개발자를 대상으로 한 ‘2021년 JS 현황’ 설문조사에서 타입스크립트를 사용하고 있는 개발자의 비율이 2016년 21%에서 5년 만에 69%로 상승한 것으로 나타났다.
이를 통해 향후 타입스크립트의 점유율이 지속적으로 상승할 것을 예측할 수 있다. 결과적으로 자바스크립트를 타입스크립트로 변환하는 것은 프로젝트를 장기적으로 관리하는 데 있어 좋은 선택지가 될 것이다.
자바스크립트에서 타입스크립트로의 변환은 다양한 에러를 수반할 수 있다. 이 장에서는 타입스크립트로의 마이그레이션 방법과, 마이그레이션 과정에서 발생할 수 있는 에러들을 해결할 수 있는 방법을 살펴 볼 것이다.
8.2 마이그레이션 가이드
8.2.1 디렉토리 설정하기
마이그레이션 가이드 파트에서는 번들러 없이 자바스크립트로 구현한 프로젝트를 마이그레이션 한다고 가정한다.
먼저 초기 프로젝트 폴더의 구조는 아래와 같다.
루트 디렉토리에 기본 문서 파일인 index.html이 있고, src 폴더에 script.js, style.css 파일이 존재한다. 여기서 우리가 타입스크립트로 마이그레이션 할 파일이 바로 script.js다.
번들러란?
웹 애플리케이션을 구성하는 리소스나 모듈을 하나로 합쳐주는 도구. 대표적으로 webpack이 있다.
컴파일한 파일이 들어갈 폴더 생성
먼저 컴파일한 자바스크립트 파일이 들어갈 ‘dist’ 폴더를 하나 생성해보자. 이 폴더에는 타입스크립트에서 자바스크립트로 컴파일한 파일이 들어간다. 마이그레이션을 진행하는 동안 컴파일된 자바스크립트와 파일이 중복되는 일이 없도록 폴더를 분리하는 것이다.
8.2.2 tsconfig.json 생성과 기본 설정
tsconfig.json은 타입스크립트를 자바스크립트로 컴파일할 때 경로와 옵션에 관한 설정 파일이다. 이 파일이 있는 위치가 프로젝트의 루트 디렉토리가 된다. 생성 후 tsc 파일명.ts 명령어를 입력할 때 tsconfig.json 파일에서 설정한 옵션에 따라 컴파일이 진행된다.
8.2.2.1 tsconfig.json 파일 생성하기
프로젝트 루트 디렉토리에 tsconfig.json 파일을 생성해 보자. 파일을 직접 생성할 수도 있지만 tsc 명령어를 이용할 수도 있다.
터미널에 아래와 같은 명령어를 입력하면 tsconfig.json 파일이 생성된다.
tsc --init
8.2.2.2 tsconfig.json 커스터마이징
tsc 명령어로 생성한 tsconfig.json 파일에는 기본적인 옵션과 주석이 포함되어있다. 필요에 따라 내용을 수정하여 옵션을 커스터마이징 할 수 있다.
타입스크립트에는 다양한 컴파일 옵션이 존재하는데, 이번 목차에서는 그중에서도 기본적으로 많이 사용되는 옵션을 위주로 살펴 볼 것이다.
공식 홈페이지의 TSConfig Reference 페이지를 확인하면 각 옵션에 대한 자세한 설명을 확인할 수 있다.
https://www.typescriptlang.org/tsconfig
8.2.2.3 include 와 exclude
include
와 exclude
는 컴파일할 대상이나 컴파일에서 제외할 대상을 지정하는 속성이다.// tsconfig.json { "include": ["./src/**.ts"], "exclude": ["node_modules", "dist"], }
include
설명 | 컴파일하고 싶은 파일 또는 디렉토리의 패턴을 지정한다. 배열에 담아서 여러 개를 지정 할 수 있다. |
기본 값 | ** |
여기서 기본 값이란 tsconfig.json 파일에 속성을 작성하지 않은 경우에 디폴트로 적용되는 값을 말한다. 만약
include
속성을 작성하지 않는다면 **
를 값으로 가진다.["./src/**.ts"]
와 같이 작성한다면 tsconfig.json 파일이 있는 위치에서 출발해서 src와 모든 하위 디렉토리에서 .ts 파일을 찾는다는 의미다.
exclude
설명 | 컴파일 대상에서 제외하고 싶은 파일 또는 디렉토리를 지정한다. 배열에 담아서 여러 개를 지정 할 수 있다. |
기본 값 | “node_modules”, “bower_components”, “jspm_packages” |
["node_modules", "dist"]
와 같이 작성한다면 node_modules 와 dist 디렉토리를 모두 제외한다는 의미다. 예시에서는 각각의 파일이 서로 의존성이 있는 폴더와 이미 컴파일 된 파일이 들어가 있는 폴더를 컴파일 대상에서 제외해주었다.include
와 exclude
에서 특정 패턴의 경로나 파일명을 지정할 때 Glob 패턴을 사용할 수 있다.
- ?
: 임의의 한 글자 매칭
- *
: 하위 디렉토리를 포함하지 않는 임의의 문자열 매칭
- **
: 하위 디렉토리를 포함한 임의의 문자열 매칭8.2.2.4 compilerOptions
compilerOptions
는 include
와 exclude
로 지정한 대상을 컴파일 과정에서 처리할 방법에 대한 속성이다.// tsconfig.json { "include": ["./src/**.ts"], "exclude": ["node_modules", "dist"], "compilerOptions": { "outDir": "./dist" "target": "ES5", "lib": ["ES5", "DOM"], "module": "commonjs", "allowJS": true, } }
outDir
설명 | 컴파일한 자바스크립트 파일이 생성될 디렉토리를 결정한다. |
기본 값 | 값을 지정하지 않으면 타입스크립트와 동일한 디렉토리에 생성된다. |
"outDir": "./dist"
로 작성 후 컴파일을 진행하면 dist 폴더에 script.js 파일이 생성된 것을 볼 수 있다.target
설명 | 컴파일 시 자바스크립트의 ECMAScript 버전을 결정한다. |
기본 값 | ES3 |
사용 가능한 값 | ES3, ES5, ES6/ES2015, ES2016, ES2017, ES2018, ES2019, ES2020, ES2021, ES2022, ESNEXT |
"target"
옵션의 값에 따라 컴파일된 자바스크립트 파일의 문법이 달라진다. 예를 들어 화살표 함수와 const
키워드를 쓴 코드가 있다.// script.ts const sum = (x: number, y: number) => { return x + y; };
"target": "ES6"
인 경우에는 화살표 함수와 const
키워드가 그대로 컴파일 된다.// script.js const sum = (x, y) => { return x + y; };
"target": "ES5"
인 경우, 화살표 함수가 일반 함수로, const
가 var
로 변경되어 컴파일 된다.// script.js var sum = function (x, y) { return x + y; };
lib
설명 | 컴파일 할 때 포함될 라이브러리의 목록을 결정한다. |
기본 값 | target 에 따라 다른 기본 값을 가진다.
target : ES3 인 경우 ⇒ DOM, ES5, ScriptHost
target : ES5 인 경우 ⇒ DOM, ES6, DOM.Iterable, ScriptHost |
사용 가능한 값 | DOM, ScriptHost, ES5, ES6/ES2015, ES2016, ES2017, ES2018, ES2019, ES2020, ES2021, ESNEXT 등 |
만약 웹 브라우저에서 동작하는 프로젝트를 진행한다면 DOM API를 가져다 쓸 것이다. 하지만 타입스크립트에서 아래와 같은 코드를 실행한다면 에러가 발생한다. 그 이유는 타입 스크립트는 기본적으로 외부 API의 타입 정보를 가지고 있지 않기 때문이다.
document.write('hello');
간단하게
lib
옵션을 사용하면 타입스크립트에게 외부 API를 사용할 것이라고 알릴 수 있다. 컴파일 옵션에 "lib": ["DOM"]
을 추가한다면 DOM과 관련된 API가 호출되어 document.write()
와 같은 메서드를 사용할 수 있게 된다.module
설명 | 컴파일 된 자바스크립트가 사용하게 될 module 방식을 결정한다. |
기본 값 | CommonJS |
사용 가능한 값 | NONE, CommonJS, AMD, UMD, SYSTEM, ES6/ES2015, ES2020, ES2022, ESNEXT, NODE16, NODENEXT |
프로젝트가 동작할 플랫폼에 따라 그에 맞는 모듈 방식을 선택할 필요가 있다. 예를 들어 ES6 문법으로 컴파일 시 import 문법을 사용하면 import가 그대로 컴파일된다. import 문법은 node 환경에서 실행이 불가능하기 때문에 모듈 옵션을 변경해주어야 하는데,
"module": "CommonJS"
를 추가하면 import 를 require 문법으로 컴파일이 가능하다.import example from './example.js'; example();
"module": "CommonJS"
인 경우 위 코드는 아래와 같이 컴파일 된다.allowJS
설명 | 컴파일 시 JS와 JSX 확장자 파일의 허용 여부를 결정한다. |
기본 값 | false |
타입스크립트는 기본적으로 컴파일 시 타입스크립트 파일 외에는 에러가 발생한다.
"allowJs : true"
인 경우에는 자바스크립트 파일을 프로젝트에 포함할 수 있다. 이 옵션은 주로 jQuery 같은 자바스크립트 기반 라이브러리를 사용하거나, 점진적으로 마이그레이션을 진행할 때 활용한다.VSCode 에디터에서 jsconfig.json 속성에 마우스 오버를 하면 설명과 함께 공식 사이트 링크를 제공한다.
8.2.3 에러 방지
타입스크립트로 파일을 변환하기 전, 앞서 생성한 tsconfig.json 파일에 컴파일 옵션을 추가해 줌으로써 초기 에러를 방지할 수 있다.
타입스크립트에는 다양한 컴파일 옵션이 존재한다. 컴파일 옵션에 대해서는 8.3 마이그레이션 이후 파트에서 더 자세하게 설명되어 있으며, 8.2.3에서는 마이그레이션의 초기 과정에 도움을 줄 수 있는 두 가지 옵션에 대해서 간단하게 살펴 볼 것이다. 다음의 두 가지 옵션을 적용하면 가장 기본적인 에러를 확인하기 편리하다.
함수의 마지막에 return을 빠뜨리는 것을 방지하는
noImplicitReturns
와, 타입 추론이 불가능하고 타입 선언이 되지 않은 값이 any로 평가되는 것을 방지하는 noImplicitAny
에 대해 알아볼 것이다..ts 파일로 변환 후 해당 옵션을 추가하고 에러를 해결해 나가도 무방하며, 지금은 .ts파일로 전환 전 가벼운 설정이라 여기면 된다.
8.2.3.1 noImplicitReturns 설정하기
다음과 같이 tsconfig.json 파일에
"noImplicitReturns": true
값을 추가해 준다.{ ... "compilerOptions": { "outDir": "./dist" "target": "ES5", "lib": ["ES5", "DOM"], "module": "commonjs", "allowJS": true, "noImplicitReturns": true } }
noImplicitReturns
가 활성화되면 함수의 모든 코드 경로를 검사하여 return 값이 빠져있는지 확인한다.다음과 같은 함수를 선언했다고 가정했을 때, 5번째 줄에 return이 빠져있는 것을 확인할 수 있다. 이와 같은 상황에서 타입스크립트는 다음과 같은 에러를 반환한다.
해당 에러를 해결할 수 있는 방법에 대해서는 8.3 마이그레이션 이후에서 더 자세하게 알아볼 것이다.
8.2.3.2 noImplicitAny 설정하기
다음과 같이 tsconfig.json 파일에
"noImplicitAny": true
값을 추가해 준다.{ ... "compilerOptions": { "outDir": "./dist" "target": "ES5", "lib": ["ES5", "DOM"], "module": "commonjs", "allowJS": true, "noImplicitReturns": true, "noImplicitAny": true } }
타입스크립트에서는 타입이 명시되지 않았거나 타입추론이 불가능한 값을 any 타입으로 평가한다.
noImplicitAny
옵션은 이러한 상황에서 any
타입으로 평가된 값에 대한 에러 반환 여부를 결정한다.타입스크립트는 해당 옵션을 활성화 시키지 않아도 경고를 나타내긴 하나, 옵션을 활성화 시키면 컴파일 시 에러를 발생시켜 컴파일을 막아 더 안전하게 코드를 작성할 수 있다.
위 형태와 같이 매개변수에 어떤 타입도 정해주지 않았을 때 다음과 같은 에러를 발생시킨다.
해당 에러를 해결할 수 있는 방법에 대해서는 8.3 마이그레이션 이후에서 더 자세하게 알아볼 것이다.
8.2.4 TypeScript 파일로 변환하기
8.2.3 까지의 과정이 완료되었다면, 타입스크립트 파일로 변환하기만 하면 된다. .js 파일은 .ts 파일로, .jsx 파일이라면 .tsx로 확장자만 변경해주면 마이그레이션이 완료된다.
파일의 확장자 명을 변경하는 것으로 마이그레이션은 완료된다.
확장자를 변경한 타입스크립트 파일을 vscode와 같은 에디터로 열어보면 군데군데 발생해 있는 에러들을 확인할 수 있을 것이다. 해당 에러들은 자바스크립트 파일로 작성할 때 에러가 발생하지 않았던 부분들이 타입스크립트에서 엄격한 체킹을 거치며 발생한 에러들이다.
또한 적용되지 않은 컴파일 옵션들을 하나씩 활성화 하였을 때, 새롭게 발생하는 에러들이 있 것이다. 따라서 타입스크립트로 마이그레이션 한 후, tsconfig.json 파일에 컴파일 옵션들을 적용하며 점진적으로 에러를 해결해 나가는 과정이 필요하다.
8.3 마이그레이션 이후파트에서는 해당 에러들을 점진적으로 해결할 수 있는 방안에 대해 살펴 볼 것이다.
8.3 마이그레이션 이후
타입스크립트로 확장자 변환을 마친 후 해당 파일에서 나타나는 에러들을 점진적으로 해결해 나가야 한다.
먼저, 8.2.3 에러 방지 파트에서 적용해 주었던 noImplicitAny, noImplicitReturns 옵션으로부터 발생한 에러의 해결 방법부터 알아 볼 것이다. 이후 컴파일 옵션들을 하나씩 적용하며 타입스크립트 코드를 더욱 엄격하게 작성할 수 있다.
8.3.1 암묵적 타입 추론 금지! noImplicit
noImplicit 옵션들은 타입이 암묵적으로 평가되는 상황을 방지하는 목적을 가지고 있다. 암묵적으로 평가되는 상황은 개발자의 의도가 반영된 것이 아니기 때문에 예상치 못한 문제를 발생시킬 수 있다. noImplicit 옵션을 활용하면 문제를 사전에 방지하여 더욱 안정성 있는 코드를 작성할 수 있다.
8.3.1.1 noImplicitAny
값 | 설명 |
true | 타입이 명시되지 않았거나 타입추론이 불가능한 값을 any 타입으로 사용하는 것을 금지한다. |
false (default) | 타입이 명시되지 않았거나 타입추론이 불가능한 값을 any 타입으로 사용하는 것을 허용한다. |
function sum(a, b) { return a + b; }
"noImplicitAny: true"
인 경우 위 코드에서 에러가 발생한다. 타입스크립트가 sum
함수의 파라미터 a, b
를 any로 암묵적으로 타입 추론하기 때문이다.any
로 평가된 값에 타입을 명시함으로써 에러를 해결할 수 있다. 암묵적으로 타입이 추론된 것이 아니라면 타입을 any
로 명시하는 것도 가능하다. 그러나 타입스크립트에서 any
타입을 사용하는 것을 지양하고 있으므로 상황에 따라 적절하게 사용하여야 한다.// 타입을 명시 function sum1(a: number, b: number) { return a + b; } // 타입을 명시 function sum2(a: any, b: any) { return a + b; }
자주 발생할 수 있는 상황으로, 변수 선언 후에 값을 할당하지 않은
let
키워드에 대한 에러를 확인할 수 있다.let count; setTimeout(function () { count++; }, 1000);
타입을 명시해주어도 되지만, 타입스크립트가 타입을 추론할 수 있도록 초기 값을 할당해주어도 에러가 해결된다.
// 초기값을 할당 let count = 0; setTimeout(function () { count++; }, 1000); // 타입을 명시 let count: number; setTimeout(function () { count++; }, 1000);
8.3.1.2 noImplicitReturns
값 | 설명 |
true | 함수가 암묵적으로 undefined 를 반환하는 것을 금지한다. |
false (default) | 함수가 암묵적으로 undefined 를 반환하는 것을 허용한다. |
function checkEmpty(item): boolean { if (typeof item== 'undefined' || item== null || item== '') { return true; } }
"noImplicitReturns: true"
인 경우 위 코드에서 에러가 발생한다. 함수가 일부 조건에서 암묵적으로 undefined를 반환하기 때문이다. checkEmpty
함수에서 if 문을 만족하는 경우에는 true
를 반환하지만, if 문을 만족하지 않는 경우에는 따로 return문을 명시하지 않아서 함수가 암묵적으로 undefined
를 반환한다.어떤 조건에서든 함수가 값을 return 할 수 있도록 return문을 명시하면 에러가 해결된다.
function checkEmpty(item): boolean { if (typeof item == 'undefined' || item == null || item == '') { return true; } else { return false; // return문 추가 } }
8.3.1.3 noImplicitOverride
값 | 설명 |
true | 메서드가 암묵적으로 오버라이딩 되는 것을 금지한다. |
false (default) | 메서드가 암묵적으로 오버라이딩 되는 것을 허용한다. |
noImplicitOverride
는 클래스를 사용하는 상황에서 적용되는 옵션이다. 값이 true
일 때 오버라이딩된 메서드에 override
키워드를 적어주지 않으면 에러가 발생한다. 이 옵션을 활용하면 부모 클래스의 메서드를 실수로 오버라이딩 하는 것을 사전에 방지할 수 있으며, override
키워드를 명시함으로써 가독성을 높일 수 있다.class Person { public name: string; public nickname: string; constructor(name: string, nickname: string) { this.name = name; this.nickname = nickname; } sayHello() { console.log('Hello!'); } get getNickname(): string { return this.nickname; } set setNickname(nickname: string) { this.nickname = nickname; } } class Student extends Person { sayHello() {} get getNickname(): string { return this.nickname; } set setNickname(nickname: string) { this.nickname = nickname; } }
"noImplicitOverride: true"
인 경우 다음과 같은 에러가 발생한다.에러를 해결하기 위해서는 자식 클래스의 오버라이딩된 메서드 앞에
override
키워드를 추가하면 된다. 만약 오버라이딩을 원하지 않는다면 에러가 발생한 메서드의 이름을 부모 클래스의 메서드와 중복되지 않게 바꿔 준다.class Person { public name: string; public nickname: string; constructor(name: string, nickname: string) { this.name = name; this.nickname = nickname; } sayHello() { console.log(`Hello ${this.name}!`); } get getNickname(): string { return this.nickname; } set setNickname(nickname: string) { this.nickname = nickname; } } class Student extends Person { override sayHello() { console.log(`Hello ${this.name}!`); } override get getNickname(): string { return this.nickname; } override set setNickname(nickname: string) { this.nickname = nickname; } }
8.3.1.4 noImplicitThis
값 | 설명 |
true | this 키워드가 암묵적으로 any 타입으로 추론되는 것을 금지한다. |
false (default) | this 키워드가 암묵적으로 any 타입으로 추론되는 것을 허용한다. |
자바스크립트의
this
는 함수가 호출되는 방식에 따라 동적으로 바인딩 된다. 이와 같은 이유로 타입스크립트에서 this
의 타입을 추론할 수 없는 상황이 생기는데, noImplicitThis
옵션은 이와 같은 상황에서 암묵적으로 any
로 타입을 추론하는 경우를 방지하는 옵션이다."noImplicitThis: true"
인 경우 아래 코드에서 에러가 발생한다. 중첩 함수가 일반 함수로 호출되면 this
는 전역 객체를 가리키게 된다. 이 때 클래스 내부에서는 this
가 undefined
를 반환하는데, 타입스크립트가 이를 any
로 타입을 추론하면서 에러가 발생한다.class Person { name: string; constructor(name: string) { this.name = name; } getName() { return function () { return this.name; // this 는 undefined }; } } const user = new Person('Son'); user.getName()();
중첩 함수의
this
를 전역 객체가 아닌 메서드의 this
와 일치시키는 방법은 다음과 같다.일반 함수 대신 화살표 함수를 사용한다. 화살표 함수의
this
는 상위 스코프의 this
를 가리키므로 중첩 함수의 this
가 메서드의 this
와 동일해지면서 에러가 해결된다.class Person { name: string; constructor(name: string) { this.name = name; } getName() { return () => { // 화살표 함수 return this.name; }; } } const user = new Person('Son'); user.getName()(); // Son
다른 방법으로는
this
를 변수 that
에 할당하여 중첩 함수 내부에서 this
대신 that
을 참조하도록 할 수 있다. 중첩 함수의 this
대신 메서드의 this
를 참조하면서 에러가 해결된다.class Person { name: string; constructor(name: string) { this.name = name; } getName() { const that = this; // 변수 that에 this를 할당 return function () { return that.name; }; } } const user = new Person('Son'); user.getName()(); // Son
8.3.2 조금 더 엄격하게! strict
strict
옵션들은 타입스크립트의 타입을 더욱 엄격하게 평가하여 프로그램의 정확성을 높여준다. 타입스크립트 팀은 strict
옵션을 strict mode family라고 지칭하고 있으며, 자바스크립트의 use strict
와 비슷한 옵션이라고 볼 수 있다. 개발자의 필요에 따라 각각의 strict
옵션을 활성화 할 수 있다. 이 장에서는 alwaysStrict
와 strictNullCheck
에 대해 살펴 볼 것이다.8.3.2.1 alwaysStrict
값 | 설명 |
true | 소스 코드에서 strict 룰을 위반한다면 에러를 발생시킨다. |
false (default) | 소스 코드에서 strict 룰을 위반하더라도 허용한다. |
해당 옵션을 활성화 할 경우, 각 소스 파일에
‘use strict’
가 적용되어 있는 것처럼 작동하며 파일을 ECMAScript 엄격 모드(Strict modee)로 분석 하고 strict룰에 위반되는 경우 에러를 발생시킨다.8.3.2.2 strictNullChecks
값 | 설명 |
true | 구체적인 값이 필요한 상황에서 값이 null 및 undefined 일 경우 에러를 발생시킨다. |
false (default) | 구체적인 값이 필요한 상황에서 값이 null 및 undefined 인 경우 무시된다. |
다음과 같은 타입스크립트 코드를 사용하는 경우,
find
메서드는 조건을 만족하는 첫 번째 요소의 값을 반환한다. 혹은 그러한 요소가 없다면 undefined
를 반환하도록 되어있으므로 loggedInUser
는 undefined
가 될 수 있다.declare const userName: string; const users = [ { name: "Kim", age: 15 }, { name: "Son", age: 28 }, ]; const loggedInUser = users.find((v) => v.name === userName); console.log(loggedInUser.age); // TypeScript 공식문서
따라서
“strictNullChecks: true”
인 경우 위의 코드를 실행하기 전에 다음과 같은 에러가 발생한다.해당 에러는 다음과 같이 if 문을 활용해서
loggedInUser
가 null
이나 undefined
인지 검사하는 방법을 사용하면 해결된다.declare const userName: string; const users = [ { name: "Kim", age: 15 }, { name: "Son", age: 28 }, ]; const loggedInUser = users.find((v) => v.name === userName); if (loggedInUser) { // if 문을 활용해 loggedInUser가 true 일 때 작동되도록 함 console.log(loggedInUser.age); } // TypeScript 공식문서
다음과 같이 옵셔널 체이닝 연산자
?
를 사용해도 해결된다.declare const userName: string; const users = [ { name: "Kim", age: 15 }, { name: "Son", age: 28 }, ]; const loggedInUser = users.find((v) => v.name === userName); console.log(loggedInUser?.age); // 옵셔널 체이닝 연산자 사용 // TypeScript 공식문서
옵셔널 체이닝(optional chaining)
옵셔널 체이닝
?.
을 사용하면 프로퍼티가 없는 중첩 객체를 에러 없이 안전하게 접근할 수 있습니다.
// 모던 JavaScript 튜토리얼8.3.3 안 쓰는 건 없애자! noUnused
Unused
옵션들은 소스 코드에서 사용하지 않거나, 실행될 수 없는 코드가 있을 경우 이를 관리할 방법에 대한 옵션들이다.8.3.3.1 noUnusedLocals
값 | 설명 |
true | 사용하지 않는 지역 변수에 대한 에러를 발생시킨다. |
false (default) | 사용하지 않는 지역 변수가 있더라도 무시한다. |
const createUserId = (userId: string) => { const id = 'one'; return { type: "Id", userId }; }; // TypeScript 공식문서
위 코드에서
id
가 선언되었으나 사용되지는 않고 있다. 해당 상황과 같이 사용되지 않는 지역변수가 있을 경우 다음과 같은 에러를 발생시킨다.위 코드에서
id
가 선언되었으나 사용되지는 않고 있다. “strictUnusedLocals: true”
인 경우, 코드를 실행하기 전 사용되지 않는 지역변수에 대한 에러가 발생한다.다음과 같이 사용되지 않는 변수를 제거해 주면 에러가 해결된다.
const createUserId = (userId: string) => { return { type: "Id", userId }; };
8.3.3.2 noUnusedParameters
값 | 설명 |
true | 사용하지 않는 인자에 대한 에러를 발생시킨다. |
false (default) | 사용하지 않는 인자가 있더라도 무시한다. |
const createUserId = (userId: string) => { const id = 'one'; return { type: "Id", userId: id }; }; // TypeScript 공식문서
위 코드에서
userID
인자는 사용되지 않고 있다. 해당 상황과 같이 사용되지 않는 인자(Parameter)가 있을 경우 다음과 같은 에러를 발생시킨다.다음과 같이 인자를 사용해 주면 에러가 해결된다.
const createUserId = (userId: string) => { const id = 'one'; return { type: "Id", userId: userId, id}; }; // TypeScript 공식문서