본문으로 건너뛰기

strict가 켜는 것들

타입스크립트 목차모듈·선언·설정레슨 48 / 51

목차

tsconfig.json의 "strict": true는 noImplicitAny와 strictNullChecks를 비롯한 핵심 엄격 검사들을 한꺼번에 켜는 묶음 스위치입니다. 여기에 noUncheckedIndexedAccess 옵션을 추가로 켜면 배열이나 인덱스 시그니처에서 값을 꺼낼 때의 undefined 가능성(TS18048)까지 검사 단계에서 미리 잡아낼 수 있습니다.

같은 코드를 놓고 옵션을 껐을 때, 기본 strict만 켰을 때, 그리고 noUncheckedIndexedAccess⁠까지 켰을 때 검사 결과가 어떻게 달라지는지 비교해 보고, 옵션을 어떻게 바꾸든 실행 결과는 늘 같다는 원리(검사 규칙 1)를 확인합니다.

5단계 중 1단계. 1~3번 줄: strict가 켜는 noImplicitAny는 타입을 안 적은 매개변수 n이 몰래 any가 되는 것을 막습니다 — TS7006.

1"strict": true가 켜는 두 기둥

"strict": true 한 줄은 여러 세부 검사 옵션을 동시에 켭니다. 그중 우리가 매일 만나는 가장 중요한 두 기둥은 **noImplicitAny**와 **strictNullChecks**입니다.

  1. noImplicitAny: 매개변수에 타입을 적지 않아 검사기가 몰래 any로 추론해야 하는 자리(function double(n))를 TS7006으로 막습니다.
  2. strictNullChecks: null과 undefined를 일반 타입(string, number)에서 분리해, let memo: string = null; 같은 대입을 TS2322로 막습니다.

아래 코드를 과목 기본 설정("strict": true)으로 검사하고 실행해 봅니다.

function double(n) {
  return n * 2;
}

let memo: string = null;
console.log(double(3), memo);
검사 결과 오류 2개
main.ts(1,17): error TS7006: Parameter 'n' implicitly has an 'any' type.main.ts(5,5): error TS2322: Type 'null' is not assignable to type 'string'.
실행 결과
6 null

만약 "strict": false로 끄면 위 두 오류가 모두 사라져 검사 오류 0이 됩니다. 하지만 실행 결과는 옵션을 켜든 끄든 똑같이 6 null입니다.

2noUncheckedIndexedAccess⁠가 더하는 검사 (TS18048)

과목 기본 설정("strict": true)만으로는 배열이나 인덱스 시그니처에서 꺼낸 값에 undefined를 붙이지 않습니다(2단원 배열 · 3단원 인덱스 시그니처). 그래서 두 칸짜리 배열에서 items[2]를 꺼내 .length를 읽어도 타입 검사는 통과하고 실행 때 TypeError로 멈춥니다.

const items = ["커피", "라테"];
const third = items[2];
console.log(third.length);
검사 결과 오류 없음
실행 결과
main.ts:3console.log(third.length);                  ^ TypeError: Cannot read properties of undefined (reading 'length')    at main.ts:3:19

이 빈틈까지 검사기가 잡게 하려면 tsconfig.json에 noUncheckedIndexedAccess 옵션을 true로 더합니다.

{
  "compilerOptions": {
    "strict": true,
    "noUncheckedIndexedAccess": true
  }
}

이 옵션을 켜면 items[2]의 지금 타입이 string이 아니라 **string | undefined**가 됩니다. 따라서 undefined를 거르지 않고 third.length를 읽으면 3번 줄에서 undefined일 수 있다는 TS18048 오류가 나며, 아래와 같이 if나 ??로 거르면 안전하게 통과합니다.

const items = ["커피", "라테"];
const third = items[2];

if (third !== undefined) {
  console.log(third.length);
} else {
  console.log("없음");
}
실행 결과
없음
코드 조각"strict": false"strict": true (과목 기본)+ "noUncheckedIndexedAccess"
function double(n)오류 없음 (n: any)TS7006 오류TS7006 오류
let memo: string = null오류 없음TS2322 오류TS2322 오류
items[2].length오류 없음 (string)오류 없음 (string)TS18048 오류 (string | undefined)
Node 실행 결과모두 같음모두 같음모두 같음

예제

실행 결과를 먼저 적어 본 뒤 펼쳐 보세요. 맞혀 보기는 점수에 들지 않습니다.

매개변수 타입, null 허용 유니언, 그리고 배열 원소 ?? 기본값을 모두 갖춘 코드입니다.

function double(
  n: number,
): number {
  return n * 2;
}

let memo: string | null = null;
const items = ["커피", "라테"];
const third = items[2] ?? "기본";

console.log(
  double(3),
  memo,
  third.length,
);

무엇이 찍힐까요?

실행 결과 보기
실행 결과
6 null 2

n: number로 noImplicitAny를, string | null로 strictNullChecks를 통과하고, items[2] ?? "기본"으로 undefined를 걸러 noUncheckedIndexedAccess⁠까지 모두 만족합니다.

자주 틀리는 곳

틀린 생각: tsconfig.json의 엄격 옵션을 바꾸면 Node 실행 결과도 달라진다.

strict나 noUncheckedIndexedAccess⁠는 오직 검사기(tsc)가 어디에 빨간 줄을 그을지만 바꿉니다(타입이 실행 때 남는다는 생각).

맞는 규칙: Node는 실행할 때 tsconfig.json의 검사 규칙을 보지 않고 타입만 지운 뒤 실행하므로, 옵션을 켜든 끄든 실행 결과는 완전히 똑같습니다(검사 규칙 1).

틀린 생각: 빨간 줄이 많이 나오면 "strict": false로 꺼서 해결하면 된다.

"strict": false로 바꾸면 당장 터미널의 TS7006이나 TS2322 메시지는 사라집니다. 하지만 그것은 화재경보기를 끈 것과 같아서, null 참조나 잘못된 인자가 들어왔을 때 실행 중에 터지는 버그는 고스란히 남습니다.

맞는 규칙: "strict": true는 항상 켜 두고, 오류가 가리키는 자리에 타입을 적거나 조건문으로 좁혀서 해결합니다.

틀린 생각: noUncheckedIndexedAccess⁠를 켜도 첫 번째 칸(items[0])은 무조건 값이 있다고 인정된다.

빈 배열([])이 들어올 수도 있기 때문에 검사기는 인덱스 숫자가 0이어도 똑같이 | undefined를 붙입니다.

맞는 규칙: noUncheckedIndexedAccess⁠를 켰다면 items[0]을 읽을 때도 if (first !== undefined)⁠나 ??로 확인해야 합니다.

확인 문제

1. "strict": true가 켜는 옵션 가운데, 매개변수 타입을 적지 않은 function add(a, b)를 TS7006으로 막아 주는 세부 옵션 이름은 무엇인가요?

힌트

1절에서 배운 두 기둥 가운데 암묵적 any를 막는 옵션 이름을 떠올려 보세요.

정답

noImplicitAny입니다. 타입을 적지 않아 암묵적으로 any가 되는 자리를 막아 줍니다.

2. 과목 기본 설정("strict": true)에 어떤 옵션을 더 켜야 const third = items[2];⁠의 타입이 string | undefined가 되나요?

힌트

2절에서 배운 인덱스 접근 검사 옵션 이름입니다.

정답

noUncheckedIndexedAccess⁠입니다. 이 옵션을 true로 켜면 인덱스로 꺼낸 값을 확인 없이 쓸 때 TS18048로 알려 줍니다.

3. "strict": true를 "strict": false로 바꾸면 node main.ts의 실행 결과가 달라질까요?

힌트

2절 끝의 비교 표 마지막 줄을 살펴보세요.

정답

달라지지 않습니다. strict 옵션은 타입 검사기(tsc)의 검사 기준만 바꿀 뿐, 타입을 지우고 실행하는 Node의 결과에는 영향을 주지 않습니다(타입이 실행 때 남는다는 생각).

컴퓨터에서 해 보기(선택) — 점수에 들지 않습니다. 폰으로만 보고 있다면 건너뛰세요. 2절의 items[2] 코드를 main.ts에 넣고 tsconfig.json에 noUncheckedIndexedAccess 옵션을 true로 추가해 npx tsc가 TS18048을 잡는지 확인해 보세요. 확인이 끝나면 noUncheckedIndexedAccess 줄은 다시 지워 과목 기본 설정으로 되돌려 둡니다. 다음은 단원 연습 문제와 단원 1~10 섞어 풀기입니다. 검사하고 돌리는 법은 내 컴퓨터에서 검사하고 돌리기에 있습니다.

끝까지 내려오면 저절로 표시됩니다. 이 기기에만 저장합니다.

타입스크립트 목차로