본문으로 건너뛰기

타입 오류 읽기

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

목차

타입 오류는 검사기가 찾은 실수를 자리 · 오류 번호 · 문장 세 조각의 한 줄로 알려 줍니다. 자리는 검사기가 실수를 발견한 곳이라, 고칠 곳은 그 줄에 쓰인 이름이 만들어진 앞줄일 수 있습니다.

검사 결과는 영어 한 줄이 길게 이어져 처음에는 막막해 보이지만, 조각마다 맡은 일이 정해져 있어 차례대로 읽으면 무엇이 어긋났는지 찾을 수 있습니다. 검사 오류는 실행하기 전에 실수를 알려 주는 정보입니다. 이 레슨에서는 한 줄을 읽는 차례와, 고칠 줄을 찾아 거슬러 가는 법을 봅니다.

8단계 중 1단계. 4번 줄의 따옴표 때문에 TS2345가 났습니다. 이 한 줄을 세 조각으로 읽습니다.

1검사 결과 한 줄의 세 조각

그림의 코드는 팁 500원을 더하는 함수에 라테 값을 넘깁니다. 4번 줄에서 4500을 따옴표 안에 적었습니다.

function addTip(price: number) {
  return price + 500;
}
let latte = '4500';
console.log(addTip(latte));
검사 결과 오류 1개
main.ts(5,20): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.

검사 결과 한 줄은 콜론(:)으로 나뉜 세 조각입니다.

조각이 오류에서알려 주는 것
자리main.ts(5,20)main.ts 파일의 5번 줄 20번째 칸 — 검사기가 실수를 발견한 곳
오류 번호error TS2345오류의 종류 — 번호가 같으면 늘 같은 꼴의 문장
문장Argument of type 'string' is not assignable to parameter of type 'number'.무엇이 어긋났나

읽는 차례는 자리 → 번호 → 문장입니다. 검사 결과 상자에서 빨간 글자로 보이는 앞머리 main.ts(5,20): error TS2345:⁠가 오류 하나의 자리와 번호입니다. 여기부터 읽습니다.

  1. 자리: 5번 줄을 찾고, 20번째 칸에서 인자 latte를 찾습니다. 칸은 줄 첫 글자를 1로 세고, 빈칸도 한 칸입니다.
  2. 번호: TS2345는 인자의 타입이 매개변수의 타입에 맞지 않는다는 오류입니다. 번호는 검색할 때나 다른 화면과 맞춰 볼 때 다리가 됩니다(4절).
  3. 문장: 'string 타입 인자는 number 타입 매개변수에 넣을 수 없다', 곧 넘긴 latte가 string이라 price의 모음 number에 들지 않는다는 뜻입니다(검사 규칙 2).

오류에 따라 문장 아래에 들여 쓴 줄이 더 붙기도 합니다. 까닭을 더 자세히 적은 줄이고, 객체 타입과 interface에서 처음 만납니다.

2오류가 난 줄과 고칠 줄

5번 줄만 보면 잘못이 없어 보입니다. 검사기가 발견한 것은 '넘긴 latte가 string'이라는 사실입니다. latte가 왜 string인지 거슬러 올라가면, latte를 만든 4번 줄에 닿습니다.

줄이름검사기가 보는 타입
5latte(넘기는 인자)string — price의 모음 number 밖
4latte(만든 줄)string — 첫 값 '4500'에서 정함

4번 줄은 latte에 타입을 적지 않아, 검사기가 첫 값 '4500'에서 string으로 정합니다(다음 레슨 적지 않아도 붙는 타입 — 추론). 4500을 따옴표 안에 적은 것이 실수의 뿌리입니다. 4번 줄의 따옴표를 지우면, 5번 줄은 그대로 두어도 오류가 사라집니다.

function addTip(price: number) {
  return price + 500;
}
let latte = 4500;
console.log(addTip(latte));
실행 결과
5000

검사 오류가 0이 되었고, 라테 4500원에 팁 500원을 더한 5000이 찍힙니다. 오류의 자리는 검사기가 실수를 발견한 곳이지, 늘 고칠 곳은 아닙니다.

3오류가 여럿이면 모두 나온다

이번에는 1절 코드 끝에 latte를 쓰는 줄을 하나 더했습니다.

function addTip(price: number) {
  return price + 500;
}
let latte = '4500';
console.log(addTip(latte));
let twice = addTip(latte) * 2;
검사 결과 오류 2개
main.ts(5,20): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.main.ts(6,20): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.

검사 결과에 두 줄이 한꺼번에 나옵니다. 검사기는 실행하지 않고 끝까지 읽으므로, 오류를 찾아도 멈추지 않고 찾은 오류를 모두 보입니다(검사 규칙 1). Node가 실행 중 오류가 난 줄에서 멈추는 것과 다릅니다. 두 오류는 번호가 같고, 둘 다 latte를 넘기는 자리입니다. 뿌리는 4번 줄 하나라, 4번 줄을 고치면 두 오류가 함께 사라집니다. 그래서 오류가 여럿이면 위에서부터 하나를 고치고 다시 검사합니다.

4같은 오류를 번호로 맞춘다

같은 오류도 보는 화면마다 꼴이 다릅니다. 어느 화면이든 오류 번호는 같아, 번호로 같은 오류인지 맞춰 봅니다.

화면1절 오류가 보이는 꼴
이 과목의 검사 결과main.ts(5,20): error TS2345: Argument of type … 한 줄
내 컴퓨터의 터미널(npx tsc)main.ts:5:20 - error TS2345: Argument of type … 다음에 5번 줄 코드와 그 아래 물결 밑줄, 맨 끝에 Found 1 error in main.ts:5
한국어로 쓰는 편집기'string' 형식의 인수는 'number' 형식의 매개 변수에 할당될 수 없습니다.

터미널은 자리를 5:20처럼 콜론으로 적고, 코드 줄 아래에 물결 밑줄을 그어 자리를 보여 줍니다. 자리를 적는 꼴만 다르고, 번호와 문장은 같습니다. 터미널에서 검사하는 법은 내 컴퓨터에서 검사하고 돌리기에서 봅니다. VS Code 같은 편집기는 화면 언어가 한국어면 오류 문장도 한국어로 보일 수 있습니다. 공식 한국어 문장의 말은 이 과목의 말과 이렇게 짝지어집니다.

한국어 문장의 말영어 원문이 과목의 말
형식type타입
인수argument인자
매개 변수parameter매개변수
할당할 수 없습니다 · 할당될 수 없습니다is not assignable to넣을 수 없다
속성property속성

플레이그라운드는 한국어 쪽에서도 오류 문장이 영어입니다. 다만 판이 6.0이라 몇몇 오류는 줄 수나 번호가 이 과목과 다르게 나오고, 그런 차이는 그 오류가 나오는 레슨에 적어 둡니다.

예제

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

function addTip(price: number) {
  return price + 500;
}
let mocha = 5000;
let latte = '4500';
console.log(addTip(mocha));
console.log(addTip(latte));

검사 결과는 몇 줄일까요? 오류가 난 줄과 고칠 줄을 쓰세요.

검사 결과 보기
검사 결과 오류 1개
main.ts(7,20): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.

예상과 다르면 그곳이 배울 곳입니다. 검사 결과는 7번 줄 하나입니다. 6번 줄의 mocha는 수 5000이라 지나갑니다. 7번 줄의 latte는 5번 줄에서 따옴표 안 '4500'으로 만들어져 string입니다. 오류가 난 줄은 7번, 고칠 줄은 5번입니다. 7번 줄을 고칠 줄로 썼다면 자리가 곧 고칠 곳이라고 본 것입니다(오류 줄이 고칠 줄이라는 생각).

자주 틀리는 곳

틀린 생각: 오류의 자리가 가리키는 줄이 고칠 줄이다.

자리는 줄과 칸까지 짚어 주니, 그곳만 고치면 될 것처럼 보입니다. 2절과 예제에서 본 것처럼, 자리는 검사기가 실수를 발견한 곳입니다.

맞는 규칙: 자리는 검사기가 실수를 발견한 곳일 뿐입니다. 그 줄에 잘못이 보이지 않으면, 그 줄에 쓰인 이름이 만들어진 줄로 거슬러 올라가 고칠 곳을 찾습니다.

틀린 생각: 검사기는 첫 오류를 찾으면 거기서 멈춘다.

실행 중 오류는 그 줄에서 실행을 멈추니, 검사도 그러리라 여기게 됩니다. 검사기는 실행하지 않으니 멈출 일이 없습니다.

const order = {
  item: '라테',
  qty: 2,
};
console.log(order.itm.length);
console.log(order.qyt);
검사 결과 오류 2개
main.ts(5,19): error TS2551: Property 'itm' does not exist on type '{ item: string; qty: number; }'. Did you mean 'item'?main.ts(6,19): error TS2339: Property 'qyt' does not exist on type '{ item: string; qty: number; }'.

검사 결과는 5번 줄과 6번 줄의 오류를 둘 다 보입니다. 실행하면 5번 줄에서 멈춰, 6번 줄은 실행되지 않습니다. order.itm이 undefined라 그 length를 꺼낼 수 없다는 실행 중 오류입니다.

맞는 규칙: 검사기는 코드를 끝까지 읽어 찾은 오류를 모두 보입니다(검사 규칙 1). 위에서부터 하나씩 고치고 다시 검사합니다.

틀린 생각: 검사 오류가 사라지면 실수도 고쳐진 것이다.

검색하면 as · any · // @ts-ignore처럼 검사 오류를 없애는 글을 만납니다. 이것들은 검사기가 그 자리를 보지 않게 덮을 뿐입니다. 덮어도 값은 그대로라, 1절 코드라면 검사 오류는 사라져도 실행 결과는 여전히 4500500입니다. 왜 쓰지 않는지는 6단원에서 봅니다.

맞는 규칙: 덮는 길은 검사 결과에서 오류만 지우고, 값과 실행 결과는 그대로 둡니다. 검사 오류는 까닭을 찾아 값이나 타입을 고쳐서 없앱니다.

확인 문제

1. 3절 코드의 4번 줄을 let latte = 4500;으로 고치고, 6번 줄에서 넘기는 latte를 '4500'으로 바꿨습니다. 검사 결과는 몇 줄이고, 몇 번 줄을 짚을까요?

function addTip(price: number) {
  return price + 500;
}
let latte = 4500;
console.log(addTip(latte));
let twice = addTip('4500') * 2;
힌트

인자를 넘기는 줄마다 넘기는 값의 타입을 적어 봅니다. 이름을 넘기면 그 이름이 만들어진 줄을 봅니다.

정답
검사 결과 오류 1개
main.ts(6,20): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.

한 줄, 6번 줄입니다. 5번 줄의 latte는 이제 수 4500이라 지나갑니다. 6번 줄은 latte 대신 따옴표 안 '4500'을 바로 넘겨 막힙니다. 이번에는 오류가 난 줄과 고칠 줄이 같습니다. 흔한 오답은 '두 줄'입니다. 3절의 결과를 그대로 떠올린 것입니다. 4번 줄을 고쳐 5번 줄 오류는 사라졌습니다.

2. 검사 결과를 읽고 고치는 차례대로 ㉠~㉤을 놓으세요.

  • ㉠ 오류 번호로 오류의 종류를 안다
  • ㉡ 자리의 줄과 칸으로 코드에서 그곳을 찾는다
  • ㉢ 그 줄에 잘못이 없으면, 쓰인 이름이 만들어진 줄로 거슬러 간다
  • ㉣ 문장으로 무엇이 어긋났는지 읽는다
  • ㉤ 한 곳을 고치고 다시 검사한다
힌트

1절의 오류를 ㉠~㉤ 차례로 따라가 봅니다. 4번 줄로 거슬러 갈 수 있었던 것은 무엇을 읽은 뒤였는지 봅니다.

놓은 뒤 물음

다 놓은 뒤에 펼쳐 이것도 고르세요. ㉢이 ㉣보다 뒤에 와야 하는 까닭은 무엇일까요?

  • ① 무엇이 어긋났는지 알아야 어느 이름을 거슬러 갈지 정할 수 있기 때문
  • ② 검사기는 오류가 난 줄의 앞줄을 읽지 않기 때문
  • ③ 오류 문장이 고칠 줄의 번호를 따로 알려 주기 때문
정답

㉡ ㉠ ㉣ ㉢ ㉤ 차례이고, 까닭은 ①입니다. ㉡과 ㉠은 바꿔도 됩니다(㉠ ㉡ ㉣ ㉢ ㉤). 번호를 먼저 보고 자리를 찾아도, 문장을 읽기 전에 둘을 마치면 됩니다.

  • ② 검사기는 코드를 처음부터 끝까지 읽습니다. 앞줄에서 정해진 타입이 오류가 난 줄까지 이어집니다.
  • ③ 문장은 무엇이 어긋났는지만 말하고, 고칠 줄은 알려 주지 않습니다(오류 줄이 고칠 줄이라는 생각).

3. 세 과목 점수의 평균을 찍는 코드입니다. 검사 결과는 몇 번 줄을 짚을까요? 고칠 곳은 몇 번 줄일까요?

function avg(total: number) {
  return total / 3;
}
let math = 90;
let art = '85';
let music = 80;
let sum = math + art + music;
console.log(avg(sum));
힌트

8번 줄에서 넘기는 sum의 타입부터 정합니다. 그 타입이 나온 줄로 한 걸음씩 거슬러 올라갑니다.

정답
검사 결과 오류 1개
main.ts(8,17): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.

검사 결과는 8번 줄을 짚고, 고칠 곳은 5번 줄입니다. sum이 string인 까닭은 7번 줄에서 글자 art를 더했기 때문입니다. 수에 글자를 더하면 글자를 이어 붙인 글자가 됩니다. art가 글자인 까닭은 5번 줄의 따옴표입니다. 5번 줄을 let art = 85;로 고치면 8번 줄 오류가 사라집니다. 흔한 오답은 8번 줄입니다. 자리가 곧 고칠 곳이라고 본 것입니다(오류 줄이 고칠 줄이라는 생각). 7번 줄이라는 답은 한 걸음만 거슬러 간 것입니다.

컴퓨터에서 해 보기(선택) — 점수에 들지 않습니다. 폰으로만 보고 있다면 건너뛰세요. 3절 코드를 플레이그라운드에 붙여 넣습니다(맨 위에 export {}; 한 줄 — 줄 번호가 하나씩 밀립니다). Errors 칸에 오류가 몇 개 나오는지 봅니다. 그다음 latte를 만든 줄의 따옴표만 지우면 두 오류가 어떻게 될지 먼저 적고, 지워서 맞춰 봅니다.

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

타입스크립트 목차로