타입 표기 이름: 타입은 그 이름이 가리킬 수 있는 값의 모음을 정합니다. 검사기는 대입하는 줄과 인자를 넘기는 줄마다, 넣으려는 값의 타입이 받는 자리의 모음에 드는지 봅니다.
자바스크립트에서는 let으로 만든 이름을 어떤 값에든 다시 붙일 수 있습니다.
수를 가리키던 이름이 어느 줄에서 글자에 붙으면, 그 뒤의 계산이 조용히 틀어집니다.
타입 표기는 그런 줄을 검사기가 찾게 합니다. 이 레슨에서 검사 규칙 2를 세웁니다.
1타입은 값의 모음이다
number는 수 값을 모두 모은 모음입니다. 0도, 4500도, -1도, 3.5도 이 모음에 듭니다.
string은 글자 값을 모두 모은 모음이라 '라테'도 '0'도 듭니다. 수 0과 글자 '0'은 다른 값이라, 서로 다른 모음에 듭니다.
| 값 | number 모음에 | string 모음에 |
|---|---|---|
0 | 든다 | 들지 않는다 |
4500 | 든다 | 들지 않는다 |
'0' | 들지 않는다 | 든다 |
'라테' | 들지 않는다 | 든다 |
이름 뒤에 : number를 붙이면 그 이름은 number 모음 안의 값만 가리킬 수 있습니다.
이렇게 이름에 적은 타입을 그 이름의 선언 타입(declared type)이라고 합니다. 선언 타입은 그 이름이 가리킬 수 있는 값의 모음이고, 선언할 때 정해져 바뀌지 않습니다.
2대입하는 줄마다 검사한다
그림의 첫 코드는 total을 number로 선언하고 세 번 값에 붙입니다.
let total: number = 0;
total = total + 4500;
total = '0';
main.ts(3,1): error TS2322: Type 'string' is not assignable to type 'number'.JS 다시 보기: =는 오른쪽을 먼저 계산해 값 하나를 만들고, 왼쪽 이름을 그 값에 붙입니다(JS '변수: let으로 이름 붙이기').
검사기도 대입하는 줄에서 오른쪽을 먼저 봅니다. 다만 값을 셈하지 않고 오른쪽의 타입을 정한 뒤, 그 타입이 왼쪽 이름의 선언 타입 모음에 드는지 봅니다.
- 1번 줄: total의 선언 타입은 number입니다. 처음 값 0은 number 모음에 들어 지나갑니다.
- 2번 줄: 오른쪽
total + 4500은 수와 수를 더한 식이라 타입이 number입니다. 검사기는 식의 값을 셈하지 않고, 이 타입이 number 모음에 드는 것만 보고 지나갑니다. - 3번 줄: 오른쪽 '0'은 글자라 타입이 string입니다. number 모음에 들지 않아 검사 오류입니다.
이 TS2322도 number 자리에 글자 값을 넣었다는 뜻입니다. 자리 main.ts(3,1)은 3번 줄 첫 칸, 곧 받는 자리인 이름 total입니다.
문장의 앞 타입 string이 넣으려는 값의 타입이고, 뒤 타입 number가 받는 자리의 타입입니다.
자바스크립트였다면 3번 줄은 아무 말 없이 total을 글자 '0'에 다시 붙였을 것입니다. 타입 표기가 있으니 검사기가 그 줄을 짚습니다.
3인자를 넘기는 줄도 같은 검사다
매개변수 뒤에 붙인 타입 표기도 모음을 정합니다. 그림의 둘째 코드는 매개변수 price를 number로 적은 함수에 글자 '4000'을 넘깁니다.
function addTip(price: number) {
return price + 500;
}
console.log(addTip('4000'));
main.ts(4,20): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.4000500JS 다시 보기: 함수를 부르면 매개변수가 인자 값에 차례로 붙습니다(JS '매개변수와 인자').
인자를 넘기는 것도 이름(매개변수)을 값에 붙이는 일입니다. 그래서 검사기는 대입과 같은 검사를 합니다. 인자 '4000'의 타입 string이 price의 선언 타입 number 모음에 드는지 보고, 들지 않아 4번 줄에서 막힙니다.
문장은 'string 타입 인자는 number 타입 매개변수에 넣을 수 없다'는 뜻입니다. Argument는 인자, parameter는 매개변수입니다. 자리 main.ts(4,20)은 4번 줄 20번째 칸, 곧 인자 '4000'입니다.
Node로 돌리면 price가 글자 '4000'에 붙어, 2번 줄은 글자 뒤에 500을 이어 붙입니다. 4500이어야 할 금액이 4000500으로 찍힙니다.
검사 규칙 2. 타입은 그 자리에 올 수 있는 값의 모음입니다. 대입하는 줄과 인자를 넘기는 줄마다, 검사기는 넣으려는 값의 타입이 받는 자리의 모음에 드는지 봅니다. 받는 자리가 이름이면 그 이름의 선언 타입으로 봅니다.
예제
검사 결과를 먼저 적어 본 뒤 펼쳐 보세요. 맞혀 보기는 점수에 들지 않습니다.
let total: number = 0;
total = total + 4000;
total = total + '500';
total = 4500;
검사를 지나갈까요? 지나가지 못하면 몇 번 줄에서 막힐까요?
검사 결과 보기
main.ts(3,1): error TS2322: Type 'string' is not assignable to type 'number'.예상과 다르면 그곳이 배울 곳입니다. 3번 줄에서 막힙니다.
JS 다시 보기: +는 한쪽이 글자면 둘을 이어 붙여 글자를 만듭니다(JS '수·글자·불리언과 typeof').
검사기는 오른쪽 식의 타입을 정할 때 이 자바스크립트 규칙을 그대로 씁니다. 수와 글자를 더한 total + '500'은 string이라, total의 선언 타입 number 모음에 들지 않습니다(검사 규칙 2).
4번 줄은 수 4500이라 지나갑니다. 3번 줄에서 오류를 찾은 뒤에도 검사기는 4번 줄까지 읽습니다.
다음은 팁 500원을 더하는 함수에 수 4000을 넘기는 코드입니다. 검사 오류가 없는 풀이 예제입니다.
function addTip(price: number) {
return price + 500;
}
const total = addTip(4000);
console.log('합계', total);
합계 4500검사기가 넣을 수 있는지 보는 자리는 4번 줄의 인자 하나입니다. 인자 4000은 number라 price의 모음에 들어 지나갑니다. 4번 줄의 total은 타입을 적지 않았는데도 검사기가 number로 봅니다. 적지 않아도 붙는 타입은 이 단원의 적지 않아도 붙는 타입 — 추론에서 봅니다.
자주 틀리는 곳
틀린 생각: 오류 문장에서 먼저 나오는 타입이 받는 자리의 타입이다.
우리말로는 받는 자리를 먼저 말하는 때가 많아, 앞 타입을 자리로 읽기 쉽습니다. 영어 문장의 차례는 반대입니다.
const price: string = 4500;
main.ts(1,7): error TS2322: Type 'number' is not assignable to type 'string'.1번 줄은 price를 string으로 적고 수 4500에 붙였습니다. 문장에 number가 먼저 나오지만, number는 넣으려는 값 4500의 타입이고 string이 받는 자리 price의 타입입니다.
맞는 규칙: is not assignable to 앞의 타입은 넣으려는 값의 타입, 뒤의 타입은 받는 자리의 타입입니다. '앞 타입의 값은 뒤 타입 자리에 넣을 수 없다'로 읽습니다(검사 규칙 2).
틀린 생각: 따옴표 안에 쓴 수는 수 값이다.
'2'는 눈으로 보면 수 2와 같아 보입니다. 따옴표가 있으면 글자입니다.
const qty: number = '2';
main.ts(1,7): error TS2322: Type 'string' is not assignable to type 'number'.'2'의 타입은 string이라 number 모음에 들지 않습니다.
맞는 규칙: 따옴표로 감싼 값은 안이 숫자여도 글자(string)라 number 모음에 들지 않습니다. 수는 따옴표 없이 씁니다(검사 규칙 2).
틀린 생각: 인자를 넘기는 줄은 대입이 아니라 타입을 검사하지 않는다.
=가 없으니 2절의 검사와 다른 일처럼 보입니다. 인자를 넘기는 것도 매개변수를 그 값에 붙이는 일입니다.
function double(n: number) {
return n * 2;
}
console.log(double('3'));
main.ts(4,20): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.6곱하기는 자바스크립트가 글자 '3'을 수로 바꿔 셈해, 실행 결과 6은 맞아 보입니다. 그래도 검사는 4번 줄을 짚습니다. 인자 '3'은 string이라 n의 모음 밖이기 때문입니다. 곱하기가 아니라 더하기였다면 '3'에 2를 이어 붙인 32가 찍혔을 것입니다.
맞는 규칙: 인자를 넘기면 매개변수가 인자 값에 붙으므로, 검사기는 대입과 같이 인자의 타입이 매개변수의 모음에 드는지 봅니다. 실행 결과가 맞아 보여도 이 검사는 같습니다(검사 규칙 2).
틀린 생각: 타입 이름은 Number처럼 대문자로 써도 같다.
자바스크립트의 Number()처럼 대문자 이름이 낯익어, 타입도 그렇게 쓰기 쉽습니다. 대문자 Number는 다른 타입입니다.
let total: Number = 0;
total = total + 4500;
main.ts(2,9): error TS2365: Operator '+' cannot be applied to types 'Number' and 'number'.1번 줄은 지나가서 맞게 쓴 것 같지만, 2번 줄에서 '+는 Number 타입과 number 타입에 쓸 수 없다'는 오류가 납니다. 대문자 쪽이 무엇인지는 원시 타입과 null·undefined에서 봅니다.
맞는 규칙: 수 타입은 소문자 number, 글자 타입은 소문자 string으로 씁니다. 대문자 Number · String은 원시 타입과 다른 타입입니다. Number는 이 코드처럼 계산하는 줄에서, String은 소문자 string 자리에 넘기는 줄에서 검사 오류가 납니다.
확인 문제
1. 예제 둘째 코드의 4번 줄을 const total = addTip('4000');으로 바꿨습니다. 검사를 지나갈까요? 지나가지 못하면 몇 번 줄에서 막힐까요? Node로 돌리면 무엇이 찍힐까요?
function addTip(price: number) {
return price + 500;
}
const total = addTip('4000');
console.log('합계', total);
힌트
4번 줄에서 넘기는 인자의 타입과, 그 인자가 붙을 매개변수의 선언 타입을 견줘 봅니다.
정답
main.ts(4,22): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.합계 4000500검사는 4번 줄에서 막힙니다. 인자 '4000'은 string이라 price의 모음 number에 들지 않습니다. Node는 타입 글자를 지우고 실행해, 2번 줄이 글자 '4000' 뒤에 500을 이어 붙입니다. 흔한 오답은 '검사를 지나고 합계 4500'입니다. 따옴표 안의 4000을 수로 보고, 실행 때 타입이 값을 바꾼다고 본 것입니다(타입이 실행 때 남는다는 생각).
2. 검사를 지나도록 1번 줄과 4번 줄의 빈칸에 타입 이름을 채우세요. 그다음 실행 결과를 쓰세요.
function cups(qty: ____) {
return qty * 4500;
}
const memo: ____ = '뜨겁게';
console.log(cups(2), memo);
힌트
5번 줄에서 qty와 memo가 어떤 값에 붙는지 봅니다. 따옴표가 있는 값과 없는 값을 가릅니다.
정답
1번 줄은 number, 4번 줄은 string입니다.
function cups(qty: number) {
return qty * 4500;
}
const memo: string = '뜨겁게';
console.log(cups(2), memo);9000 뜨겁게5번 줄의 인자 2는 수라 qty의 모음 number에 들고, '뜨겁게'는 글자라 memo의 모음 string에 듭니다.
다르게 써도 되는 곳: 4번 줄은 : ____을 통째로 지워 const memo = '뜨겁게';로 써도 검사를 지나고 결과도 같습니다(추론 — 이 단원의 추론 레슨). 1번 줄의 매개변수 타입은 지우면 검사 오류가 납니다. 매개변수는 타입을 적어야 하는 자리입니다 — 함수의 입력과 출력에서 봅니다.
흔한 오답은 1번 줄의 대문자 Number입니다. 2번 줄의 곱하기에서 검사 오류가 납니다. 4번 줄을 대문자 String으로 쓰면 이 코드는 검사를 지나지만, String은 원시 타입이 아닌 다른 타입이라 쓰지 않습니다(원시 타입과 null·undefined).
3. 오늘 걸은 걸음 수에 더 걸은 걸음을 더하고, 목표 걸음 수를 적는 코드입니다. 검사를 지나지 못하는 줄을 모두 쓰세요.
let steps: number = 3000;
steps = steps + 2500;
let goal: string = 10000;
steps = goal;
힌트
대입하는 줄마다 받는 자리(왼쪽 이름)의 선언 타입과 넣으려는 값의 타입을 한 쌍씩 적어 봅니다. 오른쪽이 이름이면 그 이름의 선언 타입을 씁니다.
정답
main.ts(3,5): error TS2322: Type 'number' is not assignable to type 'string'.main.ts(4,1): error TS2322: Type 'string' is not assignable to type 'number'.3번 줄과 4번 줄, 둘입니다. 3번 줄은 수 10000을 string으로 선언한 goal에 붙여 막힙니다. 4번 줄은 steps를 goal과 같은 값에 다시 붙입니다. 검사기가 보는 goal은 값 10000이 아니라 선언 타입 string이라, steps의 선언 타입 number 모음에 들지 않습니다(검사 규칙 2). 흔한 오답은 '3번 줄 하나'입니다. 4번 줄에서 goal이 가리키는 값 10000을 보고 수라고 본 것입니다. 검사기는 값을 셈하지 않고 선언 타입으로 봅니다.
컴퓨터에서 해 보기(선택) — 점수에 들지 않습니다. 폰으로만 보고 있다면 건너뛰세요.
2절 코드를 플레이그라운드에 붙여 넣습니다(맨 위에 export {}; 한 줄). 그다음 total = '0'; 줄을 지우면 검사 결과가 어떻게 바뀔지 먼저 적고, 지워서 맞춰 봅니다.