본문으로 건너뛰기

타입은 실행 전에 지워진다

타입스크립트 목차타입 검사기레슨 2 / 51

목차

타입스크립트 파일을 Node로 실행하면, Node는 타입 글자를 빈칸으로 바꾼 뒤 남은 자바스크립트를 실행합니다. 타입은 검사기만 읽는 글자라서 실행 때는 남지 않고, 값을 막지도 바꾸지도 않습니다.

타입 검사기가 하는 일에서는 검사 오류가 있는 코드도 Node가 끝까지 실행했습니다. 검사기가 오류를 찾았는데 실행은 왜 그대로 될까요? 이 레슨은 그 까닭을 봅니다. 검사 규칙 1의 뒤 절반, 곧 실행되는 것이 무엇인지를 세웁니다.

5단계 중 1단계. 1번 줄은 price가 수만 가리킨다고 적고, 글자 '만 원'에 붙였습니다.

1타입 표기 — 검사기만 읽는 글자

그림의 코드는 1번 줄에서 이름 price 뒤에 : number를 붙였습니다. 이름 뒤에 붙인 : 타입을 타입 표기(type annotation)라고 합니다. price가 수(number)만 가리킨다고 검사기에 알리는 글자입니다. 타입을 적는 법은 다음 레슨 타입 적기와 넣을 수 있는지 검사에서 자세히 봅니다. 그런데 1번 줄은 price를 글자 '만 원'에 붙였습니다.

const price: number = '만 원';
console.log(typeof price);
검사 결과 오류 1개
main.ts(1,7): error TS2322: Type 'string' is not assignable to type 'number'.
실행 결과
string

검사 결과의 자리 main.ts(1,7)은 1번 줄 7번째 칸, 곧 이름 price입니다. is not assignable to는 '넣을 수 없다'입니다. 문장 전체는 'string 타입은 number 타입에 넣을 수 없다', 곧 number 자리에 글자 값을 넣었다는 뜻입니다. 앞의 타입이 넣으려는 값의 타입이고, 뒤의 타입이 받는 자리의 타입입니다.

실행 결과는 string입니다.

JS 다시 보기: typeof는 값의 종류를 'number'·'string' 같은 글자로 돌려줍니다(JS '수·글자·불리언과 typeof').

price가 가리키는 값은 글자 '만 원' 그대로입니다. : number는 글자 값을 막지도, 수로 바꾸지도 않았습니다. 그리고 검사 오류가 있는데도 Node는 2번 줄까지 실행했습니다.

2Node는 타입 글자를 지우고 실행한다

JS 다시 보기: Node는 node main.js처럼 받은 파일을 위에서부터 실행합니다(JS '내 컴퓨터에서 돌려 보기').

이 과목의 Node 26은 node main.ts처럼 타입스크립트 파일도 받습니다. 받은 파일에서 먼저 타입 글자를 같은 폭의 빈칸으로 바꾸고, 남은 자바스크립트를 실행합니다. 이것을 타입 지우기(type stripping)라고 합니다. Node는 이때 검사를 하지 않습니다. Node 문서도 타입 문법을 빈칸으로 바꿀 뿐, 타입 검사는 하지 않는다고 적습니다.

1절 코드에서 Node가 실제로 실행하는 자바스크립트는 다음과 같습니다. : number 여덟 칸이 빈칸 여덟 칸이 되었습니다.

const price         = '만 원';
console.log(typeof price);
실행 결과
string

남은 코드는 자바스크립트 그대로라, 실행 결과도 자바스크립트의 규칙 그대로입니다. 글자 값의 typeof는 string입니다. 빈칸으로 바꾸니 줄과 칸의 자리도 그대로입니다. 실행 중 오류가 나도 줄 번호가 내 파일과 같습니다.

이 과목에서 쓰는 타입스크립트는 자바스크립트에 타입 글자를 더한 것입니다. 그래서 타입 글자를 지우면 자바스크립트가 남고, 실행은 자바스크립트를 돌리는 Node가 맡습니다. 타입은 검사기만 봅니다. 다만 빈칸으로 지울 수 있는 타입 글자여야 합니다. 지울 수 없는 문법을 만나면 Node도 돌리지 못하고 멈춥니다(뒤 레슨에서 만납니다).

검사 규칙 1. 검사기는 코드를 실행하지 않고 읽어, 타입이 맞는지만 봅니다. 실행되는 것은 타입 글자를 지운 자바스크립트라, 타입은 실행 때 남지 않습니다. 그래서 타입은 값을 막지도 바꾸지도 않고, 검사 오류가 있어도 Node는 실행합니다.

3검사는 따로, 실행 전에 한다

Node가 검사하지 않으니, 검사는 검사기에 따로 맡깁니다. 코드를 쓰는 동안에는 편집기가 물결 밑줄로 알려 주고, 명령으로는 tsc를 돌립니다.

검사 결과에 오류가 남은 채 실행 결과만 보고 넘어가면, 1절처럼 수가 와야 할 자리에 글자가 흘러갑니다. 그래서 차례를 지킵니다. 내 컴퓨터에서는 npx tsc로 검사 오류가 0인지 먼저 보고, 그다음 node main.ts로 실행합니다. 두 명령은 이 단원의 마지막 레슨 내 컴퓨터에서 검사하고 돌리기에서 씁니다.

이 과목의 예제는 두 결과를 상자 머리로 가릅니다. '검사 결과' 상자 없이 '실행 결과' 상자만 있는 예제는 검사 오류가 0인 코드입니다.

예제

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

total이 수만 가리킨다고 적었는데, 2번 줄에서 total을 글자 '4500'에 다시 붙였습니다.

let total: number = 4000;
total = '4500';
console.log(total + 500);

검사를 지나갈까요? 지나가지 못하면 몇 번 줄에서 막힐까요? Node로 돌리면 무엇이 찍힐까요?

검사 결과와 실행 결과 보기
검사 결과 오류 1개
main.ts(2,1): error TS2322: Type 'string' is not assignable to type 'number'.
실행 결과
4500500

예상과 다르면 그곳이 배울 곳입니다. 검사는 2번 줄에서 막힙니다. number 자리에 글자 값을 넣었다는 TS2322이고, 자리 main.ts(2,1)은 2번 줄 첫 칸의 total입니다. 실행 결과를 5000으로 예상했다면, : number가 글자 '4500'을 수로 바꾼다고 본 것입니다(타입이 실행 때 남는다는 생각). 타입 글자는 지워지고, 3번 줄은 자바스크립트 규칙대로 글자 '4500' 뒤에 500을 이어 붙여 4500500을 찍습니다(검사 규칙 1).

다음 코드는 검사 오류가 없습니다.

const item: string = '라테';
const qty: number = 2;
console.log(item, qty);
검사 결과 오류 없음

Node가 실행하는 자바스크립트를 줄마다 써 보고, 실행 결과도 적어 보세요.

지운 코드와 실행 결과 보기
const item         = '라테';
const qty         = 2;
console.log(item, qty);
실행 결과
라테 2

타입 표기 : string과 : number가 같은 폭의 빈칸이 되었고, 3번 줄은 그대로입니다. 빈칸 없이 const item = '라테';처럼 써도 같은 자바스크립트입니다. Node는 줄과 칸의 자리를 맞추려고 빈칸으로 바꿀 뿐입니다.

자주 틀리는 곳

틀린 생각: 타입 표기는 실행 때도 남아 맞지 않는 값을 막는다.

: number를 적으면 그 이름에 수만 오도록 지켜 줄 것 같습니다. 타입 표기는 검사기만 읽고, 실행 전에 지워집니다.

const qty: number = '3';
console.log(qty, typeof qty);
검사 결과 오류 1개
main.ts(1,7): error TS2322: Type 'string' is not assignable to type 'number'.
실행 결과
3 string

검사는 1번 줄을 짚었지만, Node는 글자 '3'을 그대로 받아 찍습니다. typeof로 보면 값은 여전히 글자입니다.

맞는 규칙: 타입 표기는 실행 전에 지워져, 실행 때 값을 막지도 바꾸지도 않습니다. 맞지 않는 값은 검사 결과에서 찾아 고칩니다(검사 규칙 1).

틀린 생각: 검사 오류가 있으면 Node는 실행하지 않는다.

검사 오류는 실행 전에 나오니, 실행도 그 자리에서 막힐 것 같습니다. Node는 검사하지 않습니다.

const cups: number = '두 잔';
console.log('주문 시작');
console.log(cups);
검사 결과 오류 1개
main.ts(1,7): error TS2322: Type 'string' is not assignable to type 'number'.
실행 결과
주문 시작
두 잔

검사는 1번 줄을 짚었지만, Node는 세 줄을 모두 실행했습니다. 검사를 먼저 하려면 검사기를 따로 돌립니다.

맞는 규칙: Node는 타입 글자를 지우기만 하고 검사하지 않아, 검사 오류가 있어도 끝까지 실행합니다. 그래서 npx tsc로 검사 오류가 0인지 본 뒤 node main.ts로 실행합니다(검사 규칙 1).

틀린 생각: 타입을 적으면 값이 그 타입으로 바뀐다.

: number를 적었으니 글자 '4500'도 수 4500이 되리라 여기게 됩니다. 값을 바꾸는 것은 타입 표기가 아니라 실행되는 코드입니다.

const text = '4500';
const price: number = text;
console.log(price + 500);
검사 결과 오류 1개
main.ts(2,7): error TS2322: Type 'string' is not assignable to type 'number'.
실행 결과
4500500

price가 가리키는 값은 글자 '4500'이라, 3번 줄은 글자 뒤에 500을 이어 붙입니다. 글자를 수로 바꾸려면 Number()를 부릅니다.

JS 다시 보기: Number('4500')은 글자를 수 4500으로 바꿉니다(JS '글자를 수로: Number와 NaN').

const text = '4500';
const price: number =
  Number(text);
console.log(price + 500);
실행 결과
5000

2~3번 줄은 한 문장을 폰 화면에 맞추려고 = 뒤에서 나눈 것입니다. Number(text)가 돌려준 값은 수라 검사도 지나고, 4번 줄은 수끼리 더해 5000을 찍습니다.

맞는 규칙: 타입 표기는 이름이 가리킬 값의 타입을 검사기에 알릴 뿐, 값을 바꾸지 않습니다. 값을 바꾸는 일은 Number()처럼 실행되는 코드가 합니다(검사 규칙 1).

틀린 생각: 실행 중 오류가 다시 찍은 코드 줄은 내 파일의 그 줄과 글자까지 같다.

오류 메시지는 오류가 난 줄을 다시 찍어 보여 주니, 내가 쓴 줄 그대로일 것 같습니다. 타입스크립트 파일에서는 타입 글자 자리가 빈칸으로 찍힙니다.

const qty: number = 2;
const text: string = qty.trim();
console.log(text);
검사 결과 오류 1개
main.ts(2,26): error TS2339: Property 'trim' does not exist on type 'number'.
실행 결과
main.ts:2const text         = qty.trim();                         ^ TypeError: qty.trim is not a function    at main.ts:2:26

실행 결과에 다시 찍힌 2번 줄은 : string 자리가 빈칸 여덟 칸입니다. Node가 타입 글자를 지운 코드를 실행했다는 흔적입니다. 빈칸으로 바꿔 자리가 그대로라, main.ts:2와 2:26은 내 파일의 2번 줄 26번째 칸을 그대로 가리킵니다. 검사기는 같은 실수를 실행 전에 같은 자리에서 짚었습니다. trim은 글자에만 있고 수에는 없는 메서드입니다.

맞는 규칙: Node는 타입 글자를 같은 폭의 빈칸으로 바꿔 실행하므로, 실행 중 오류의 코드 줄에는 타입 자리가 빈칸으로 보입니다. 줄 번호와 칸 번호는 내 파일과 같으니, 그 자리를 내 파일에서 찾아 읽습니다(검사 규칙 1).

확인 문제

1. 1절 코드의 1번 줄을 const price: string = 10000;⁠으로 바꿨습니다. 검사를 지나갈까요? 지나가지 못하면 몇 번 줄에서 막힐까요? Node로 돌리면 무엇이 찍힐까요?

const price: string = 10000;
console.log(typeof price);
힌트

1번 줄에서 적은 타입과 값의 종류를 따로 봅니다. 실행 쪽은 Node가 실행하는 코드에 무엇이 남는지 떠올립니다.

정답
검사 결과 오류 1개
main.ts(1,7): error TS2322: Type 'number' is not assignable to type 'string'.
실행 결과
number

검사는 1번 줄에서 막힙니다. 이번에는 넣으려는 값이 number, 받는 자리가 string이라, 문장의 두 타입이 1절과 자리를 바꿨습니다. Node는 타입 글자를 지우고 실행해, 값 10000의 typeof인 number를 찍습니다. 흔한 오답은 string입니다. 적은 타입이 실행 때 남아 값을 바꾼다고 본 것입니다(타입이 실행 때 남는다는 생각). 아무것도 찍히지 않는다는 답은 검사 오류가 실행을 막는다고 본 것입니다(검사 오류가 실행을 막는다는 생각).

2. 1절 코드가 검사를 지나도록 1번 줄의 빈칸에 타입을 채우세요. 그다음 실행 결과를 쓰세요.

const price: ____ = '만 원';
console.log(typeof price);
힌트

1번 줄에서 price가 붙는 값의 종류를 봅니다. 따옴표가 있는지 봅니다.

정답

빈칸은 string입니다.

const price: string = '만 원';
console.log(typeof price);
실행 결과
string

'만 원'은 글자라 string 자리에 넣을 수 있습니다. 실행 결과는 1절과 같은 string입니다. 타입 표기는 지워지므로, number로 적었을 때와 실행 결과가 같습니다. 다르게 써도 되는 곳: : ____을 통째로 지워 const price = '만 원';으로 써도 검사를 지나고 결과도 같습니다. 타입을 적지 않으면 검사기가 값에서 타입을 정합니다 — 적지 않아도 붙는 타입 — 추론에서 봅니다. 흔한 오답은 number입니다. '만 원'이라는 금액의 뜻을 보고 타입을 고른 것입니다. 타입은 값의 종류이고, 따옴표 안 '만 원'은 글자입니다.

3. 어제와 오늘 걸은 걸음 수를 더해 찍는 코드입니다. 검사를 지나갈까요? 지나가지 못하면 몇 번 줄에서 막힐까요? Node로 돌리면 무엇이 찍힐까요?

const today: number = 8000;
const yesterday: string = 6500;
console.log(today + yesterday);
힌트

1번 줄과 2번 줄마다 적은 타입과 값의 종류를 견줘 봅니다. 3번 줄은 Node가 실행할 때 두 이름이 가리키는 값으로 셈합니다.

정답
검사 결과 오류 1개
main.ts(2,7): error TS2322: Type 'number' is not assignable to type 'string'.
실행 결과
14500

검사는 2번 줄에서 막힙니다. 6500은 수인데 string 자리에 넣었습니다. 3번 줄은 검사기에게 수 + 글자인데, +는 글자를 이어 붙일 수 있어 막지 않습니다. Node는 타입 글자를 지우고 실행하므로 yesterday는 수 6500 그대로이고, 8000 + 6500 = 14500이 찍힙니다. 흔한 오답은 80006500입니다. : string이 6500을 글자로 바꿔, 3번 줄이 글자를 이어 붙인다고 본 것입니다(타입이 실행 때 남는다는 생각). 아무것도 찍히지 않는다는 답은 검사 오류가 실행을 막는다고 본 것입니다(검사 오류가 실행을 막는다는 생각).

컴퓨터에서 해 보기(선택) — 점수에 들지 않습니다. 폰으로만 보고 있다면 건너뛰세요. 1절 코드를 플레이그라운드에 붙여 넣습니다(맨 위에 export {}; 한 줄 — 타입 검사기가 하는 일의 '해 보기'). 그다음 '만 원'을 10000으로 바꾸면 검사 결과와 실행 결과가 어떻게 바뀔지 먼저 적고, 바꿔서 맞춰 봅니다. .JS 칸을 누르면 플레이그라운드가 타입 글자를 뺀 자바스크립트를 보여 줍니다. Node와 달리 빈칸을 남기지 않고 줄을 다시 써서 보여 줍니다.

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

타입스크립트 목차로