본문으로 건너뛰기

적지 않아도 붙는 타입 — 추론

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

목차

타입을 적지 않으면 검사기는 이름의 첫 값에서 타입을 정합니다. 이것을 추론(inference)이라고 합니다. let은 첫 값을 넓혀 string · number로 정하고, const로 만든 글자 · 수 하나는 그 값 하나짜리 타입으로 정합니다.

지금까지의 예제는 이름마다 : number처럼 타입을 적었습니다. 타입스크립트 코드는 대부분 타입을 적지 않아도 됩니다. 검사기가 첫 값을 보고 정하기 때문입니다. 이 레슨에서 검사 규칙 3을 세우고, 검사기가 줄마다 보는 '지금 타입'에 이름을 붙입니다.

7단계 중 1단계. 표의 칩은 그 줄에서 검사기가 보는 지금 타입입니다.

1첫 값에서 타입을 정한다

JS 다시 보기: let 이름은 다른 값에 다시 붙일 수 있고, const 이름은 다시 붙일 수 없습니다(JS '이름표 다시 붙이기와 const').

그림의 코드는 네 줄 어디에도 타입을 적지 않았습니다.

let size = 'tall';
const cup = 'tall';
let count = 0;
count = '1';
검사 결과 오류 1개
main.ts(4,1): error TS2322: Type 'string' is not assignable to type 'number'.

검사기는 이름마다 첫 값을 보고 타입을 이렇게 정합니다. 편집기에서 이름에 마우스를 올리면 보이는 타입입니다.

줄이름검사기가 정한 타입
1sizestring
2cup"tall"
3countnumber

1번 줄의 size는 첫 값이 'tall'입니다. let 이름은 뒤에 다른 글자에 다시 붙을 수 있으니, 검사기는 'tall' 하나가 아니라 글자 전체로 넓혀 string으로 정합니다. 이렇게 첫 값보다 넓은 타입으로 정하는 것을 넓힌다(widening)고 합니다. 3번 줄의 count도 첫 값 0을 넓혀 number로 정합니다. 이렇게 적지 않은 타입을 검사기가 값에서 정하는 일이 추론입니다. 추론한 타입도 적은 타입처럼 그 이름의 선언 타입이 됩니다.

2const로 만든 글자·수 하나는 그 값 하나

2번 줄의 cup은 const라 다시 붙일 수 없습니다 — cup = 'grande';처럼 대입하면 TS2588('상수라 대입할 수 없다')로 막힙니다. 그래서 검사기는 cup의 타입을 값 'tall' 하나만 든 모음으로 정하고, "tall"이라고 적습니다. 큰따옴표는 검사기가 타입을 적는 꼴일 뿐, 코드의 작은따옴표 'tall'과 같은 값입니다. 값 하나짜리 타입은 리터럴 유니언으로 값 고르기에서 다시 봅니다.

const로 만든 객체라도 속성은 넓혀 정합니다. const 이름은 다시 붙일 수 없어도, 객체의 속성은 다른 값에 다시 붙일 수 있기 때문입니다.

const order = { size: 'tall' };
order.size = 'grande';
order.size = 3;
검사 결과 오류 1개
main.ts(3,1): error TS2322: Type 'number' is not assignable to type 'string'.

2번 줄은 지나가고, 3번 줄의 문장은 받는 자리를 string이라고 말합니다. order.size의 타입은 "tall"이 아니라 string입니다.

3다시 대입해도 선언 타입은 그대로 — 지금 타입

1절 코드의 4번 줄은 count를 글자 '1'에 다시 붙입니다. 자바스크립트라면 아무 말 없이 붙는 줄입니다. 검사기는 3번 줄에서 첫 값으로 정한 선언 타입 number로 이 줄을 검사합니다. 이 TS2322도 number 자리에 글자 값을 넣었다는 뜻입니다. 타입을 적지 않아도, 첫 값에서 정해진 선언 타입이 그 이름의 약속이고 다시 대입해도 바뀌지 않습니다.

검사기가 그 줄에서 보는 이름의 타입을 지금 타입이라고 부릅니다. 편집기에서 마우스를 올리면 보이는 것과 그림의 칩이 지금 타입입니다. 이 단원의 코드에서는 지금 타입이 늘 선언 타입과 같습니다. 둘이 갈리는 곳은 4단원에서 봅니다.

파이썬 과목을 거쳐 왔다면, 파이썬 그림의 값 칸 머리 int · str은 값의 종류였습니다. 이 과목의 타입은 이름이 가리킬 수 있는 값의 모음이라 이름에 붙어 다닙니다.

검사 규칙 3. 이름의 선언 타입은 선언할 때 정해집니다. 타입을 적으면 적은 타입, 적지 않으면 첫 값에서 추론한 타입입니다 — let과 객체의 속성은 넓혀 string · number로, const로 만든 글자 · 수 하나는 그 값 하나로 정합니다. 다시 대입해도 선언 타입은 그대로입니다.

예제

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

let menu = '라테';
const price = 4500;
let qty = 2;
const memo = '얼음 적게';
검사 결과 오류 없음

검사 오류가 없는 코드입니다. 편집기에서 menu · price · qty · memo에 마우스를 올리면 보이는 지금 타입을 하나씩 쓰세요.

지금 타입 보기
이름지금 타입
menustring
price4500
qtynumber
memo"얼음 적게"

예상과 다르면 그곳이 배울 곳입니다. let으로 만든 menu · qty는 넓혀 string · number이고, const로 만든 price · memo는 그 값 하나입니다(검사 규칙 3). price처럼 수도 const면 값 4500이 곧 타입입니다.

다음 코드는 검사를 지나갈까요? 지나가지 못하면 몇 번 줄에서 막힐까요?

const big = 'grande';
let size = 'tall';
size = big;
검사 결과 보기
검사 결과 오류 없음

예상과 다르면 그곳이 배울 곳입니다. 검사 오류 없이 지나갑니다. size의 선언 타입은 첫 값을 넓힌 string이고, big의 지금 타입 "grande"는 string 모음에 듭니다. 3번 줄에서 막힌다고 예상했다면, let으로 만든 size도 'tall' 하나짜리 타입이라고 본 것입니다(넓어지지 않는다는 생각).

자주 틀리는 곳

틀린 생각: let으로 만든 이름도 첫 값 하나짜리 타입이다.

const의 cup이 "tall"이니, 같은 'tall'로 시작한 let의 size도 그러리라 여기게 됩니다. let 이름은 넓혀 정합니다.

let size = 'tall';
size = 'grande';
size = 3;
검사 결과 오류 1개
main.ts(3,1): error TS2322: Type 'number' is not assignable to type 'string'.

2번 줄은 다른 글자 'grande'라도 지나갑니다. 3번 줄의 문장은 받는 자리를 string이라고 말합니다. size의 선언 타입은 "tall"이 아니라 string입니다.

맞는 규칙: let 이름과 객체의 속성은 뒤에 다른 값에 붙을 수 있어, 검사기가 첫 값을 넓혀 string · number로 정합니다. 값 하나짜리 타입은 const로 만든 글자 · 수 하나뿐입니다(검사 규칙 3).

틀린 생각: 타입을 적지 않은 이름은 자바스크립트처럼 어떤 값에든 다시 붙일 수 있다.

타입을 적지 않았으니 검사기도 그 이름을 보지 않을 것 같습니다. 첫 값에서 정한 타입으로 똑같이 검사합니다.

let count = 0;
count = '1';
console.log(count);
검사 결과 오류 1개
main.ts(2,1): error TS2322: Type 'string' is not assignable to type 'number'.
실행 결과
1

Node는 그대로 실행해 글자 '1'을 찍지만, 검사기는 2번 줄을 짚습니다. count의 선언 타입은 첫 값 0에서 정한 number입니다.

맞는 규칙: 적지 않아도 첫 값에서 정한 선언 타입이 그 이름의 약속이라, 검사기는 다시 대입하는 줄을 그 타입으로 검사합니다. 수도 글자도 가리킬 이름은 4단원의 유니언으로 처음부터 적습니다(검사 규칙 3).

틀린 생각: 타입은 모두 적어야 검사가 안전하다.

적지 않으면 검사가 느슨해질 것 같아, 이름마다 타입을 적고 싶어집니다. 검사기는 추론한 타입으로도 똑같이 검사합니다.

let total = 0;
total = '0';
검사 결과 오류 1개
main.ts(2,1): error TS2322: Type 'string' is not assignable to type 'number'.

타입 적기와 넣을 수 있는지 검사의 let total: number = 0;⁠과 같은 오류가 같은 줄에 납니다. 타입스크립트 핸드북(TypeScript Handbook)도 대부분은 타입을 적을 필요가 없다고 합니다. 다만 매개변수는 첫 값이 없어 추론할 수 없으니 적습니다. 함수의 입력과 출력에서 봅니다.

맞는 규칙: 검사기는 추론한 타입으로도 적은 타입과 똑같이 검사합니다. 첫 값에서 정해지는 곳은 검사기에 맡기고, 매개변수처럼 첫 값이 없는 곳에 적습니다(검사 규칙 3).

확인 문제

1. 1절 코드의 3번 줄을 const count = 0;으로 바꿨습니다. 3번 줄 count의 지금 타입은 무엇이고, 검사 결과는 어떻게 될까요?

let size = 'tall';
const cup = 'tall';
const count = 0;
count = '1';
힌트

2번 줄의 cup과 같은 꼴인지 봅니다. 4번 줄에서는 const 이름을 다시 붙이려 한다는 것을 봅니다.

정답
검사 결과 오류 1개
main.ts(4,1): error TS2588: Cannot assign to 'count' because it is a constant.

count의 지금 타입은 0입니다. const로 만든 수 하나라 그 값 하나짜리 타입입니다(검사 규칙 3). 4번 줄의 오류는 TS2322에서 TS2588로 바뀝니다. 'count는 상수라 대입할 수 없다', 곧 const 이름을 다시 붙이려 했다는 오류입니다. 자바스크립트도 이 줄을 실행하면 TypeError로 멈추는데, 검사기는 실행하기 전에 짚습니다. 흔한 오답은 지금 타입 number입니다. const도 let처럼 넓힌다고 본 것입니다.

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

let size: ____ = 'tall';
size = 'grande';
console.log(size);
힌트

2번 줄에서 size가 다시 붙는 값을 봅니다. 그 값도 넣을 수 있는 모음이어야 합니다.

정답

빈칸은 string입니다.

let size: string = 'tall';
size = 'grande';
console.log(size);
실행 결과
grande

'tall'과 'grande'가 모두 드는 모음은 string입니다. 다르게 써도 되는 곳: : ____을 통째로 지워 let size = 'tall';로 써도, 검사기가 첫 값을 넓혀 string으로 정해 지나갑니다. 이 과목은 이쪽을 권합니다(검사 규칙 3). 흔한 오답은 'tall'입니다. 그러면 size가 'tall' 하나짜리 타입이 되어 2번 줄에서 막힙니다(넓어지지 않는다는 생각).

3. 걸음 수를 세는 코드입니다. 검사를 지나지 못하는 줄은 몇 번 줄일까요? 3번 줄을 읽은 뒤 steps와 goal의 지금 타입도 쓰세요.

let steps = 3000;
const goal = 10000;
steps = steps + 2500;
steps = '5500';
힌트

let으로 만든 이름과 const로 만든 이름을 가릅니다. 4번 줄은 steps의 선언 타입으로 검사합니다.

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

4번 줄에서 막힙니다. steps의 선언 타입은 첫 값 3000을 넓힌 number라 글자 '5500'은 넣을 수 없습니다. 3번 줄 뒤 steps의 지금 타입은 number, goal의 지금 타입은 10000입니다. 3번 줄은 수와 수를 더해 number라 지나갑니다. 흔한 오답은 goal을 number로 쓴 답입니다. const도 넓힌다고 본 것입니다. steps를 3000으로 쓴 답은 let도 그 값 하나라고 본 것입니다(넓어지지 않는다는 생각).

컴퓨터에서 해 보기(선택) — 점수에 들지 않습니다. 폰으로만 보고 있다면 건너뛰세요. 1절 코드를 플레이그라운드에 붙여 넣고(맨 위에 export {}; 한 줄), 이름마다 마우스를 올려 지금 타입을 봅니다. 그다음 let size 줄의 let을 const로 바꾸면 size의 지금 타입이 어떻게 바뀔지 먼저 적고, 바꾼 뒤 마우스를 올려 맞춰 봅니다.

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

타입스크립트 목차로