TypeScript는 탐정입니다
셜록 홈즈는 처음 만나는 사람을 보고도 직업, 출신, 최근 행동을 꿰뚫어 봅니다. 손에 굳은살이 있고, 자세가 곧으며, 군화 자국이 남아있다면 "군인이시군요"라고 말합니다. 아무도 알려주지 않았지만, 단서를 보고 스스로 추론한 것입니다.
TypeScript도 마찬가지입니다. 여러분이 타입을 직접 써주지 않아도, 코드를 보고 스스로 타입을 알아냅니다. 이것을 타입 추론(Type Inference)이라고 합니다.
초기값을 보고 알아낸다
가장 간단한 추론은 변수에 초기값을 넣을 때 일어납니다.
// 타입을 명시하지 않아도let name = "김민수";let age = 25;let isStudent = true;
TypeScript는 "김민수"라는 값을 보고 name이 string임을 압니다. 25를 보고 age가 number임을 압니다. 탐정처럼 단서를 보고 타입을 추론한 것입니다.
실제로 위 코드는 아래와 완전히 동일합니다.
// 타입을 명시한 경우let name: string = "김민수";let age: number = 25;let isStudent: boolean = true;
타입을 알고 있으니, 잘못된 값을 넣으면 여전히 에러가 납니다.
let age = 25;age = "스물다섯"; // 에러! Type 'string' is not assignable to type 'number'.
함수 반환값도 추론한다
함수가 어떤 값을 반환하는지도 TypeScript가 알아냅니다.
function add(a: number, b: number) { return a + b;}const result = add(3, 5);// result의 타입은 number — TypeScript가 추론함
a와 b가 number이고, 그 둘을 더하면 number가 된다는 것을 TypeScript는 압니다. 반환 타입을 따로 쓰지 않아도 됩니다.
조건에 따라 다른 타입을 반환하는 경우도 추론합니다.
function greet(isKorean: boolean) { if (isKorean) { return "안녕하세요"; } return "Hello";}const msg = greet(true);// msg의 타입은 string — TypeScript가 추론함
추론이 안 되는 경우 — 매개변수
그런데 탐정도 단서가 없으면 추론할 수 없습니다. 함수의 매개변수가 바로 그런 경우입니다.
function double(n) { // 에러! Parameter 'n' implicitly has an 'any' type. return n * 2;}
n이 무엇인지 알 수 없습니다. 이 함수를 호출할 때 숫자를 넣을지, 문자열을 넣을지, TypeScript는 알 방법이 없습니다. 이 에러는 tsconfig.json에서 strict: true를 설정했을 때 나타납니다. PART 07에서 tsconfig.json을 자세히 다룹니다. 매개변수는 반드시 타입을 직접 써줘야 합니다.
function double(n: number) { return n * 2;}
명시적 표기 vs 추론 — 언제 뭘 쓸까
그렇다면 매번 타입을 써야 할까요? 그렇지 않습니다. 규칙은 단순합니다.
추론에 맡겨도 되는 경우는 초기값이 명확할 때입니다.
const count = 0; // 굳이 : number 안 써도 됨const message = "hello"; // 굳이 : string 안 써도 됨const flag = true; // 굳이 : boolean 안 써도 됨
직접 써줘야 하는 경우는 초기값 없이 선언하거나, 함수 매개변수를 정의할 때입니다.
let username: string; // 초기값 없이 선언 — 타입 명시 필요function greet(name: string) { // 매개변수 — 타입 명시 필요 return `안녕하세요, ${name}!`;}
초기값 없이 선언하고 타입도 안 쓰면 어떻게 될까요.
let username;username = "김민수"; // 이건 됨username = 42; // 이것도 됨... 왜냐면 any 타입이 되어버려서
TypeScript가 추론할 단서가 없으니 any 타입이 됩니다. any 타입은 뭐든 담을 수 있어서 타입 검사를 전혀 받지 못합니다. 이것은 다음다음 챕터에서 자세히 다룹니다.
추론 결과를 눈으로 확인하는 법
VS Code에서 변수 위에 마우스를 올리면 TypeScript가 추론한 타입이 팝업으로 나타납니다. 직접 확인해보세요.
const name = "김민수"; // 위에 마우스 올리면: const name: "김민수"let count = 0; // 위에 마우스 올리면: let count: number
const로 선언한 name은 string이 아니라 "김민수"라는 정확한 값이 타입이 됩니다. 값이 변할 수 없으니 더 좁은 타입으로 추론된 것입니다. let으로 선언한 count는 나중에 값이 바뀔 수 있으니 number로 넓게 추론합니다.
타입 추론 정리
| 상황 | 추론 여부 | 예시 |
|---|---|---|
| 초기값 있는 변수 선언 | 자동 추론 | let n = 5 → number |
| 함수 반환값 | 자동 추론 | return a + b → number |
| 함수 매개변수 | 직접 써야 함 | (n: number) |
| 초기값 없는 변수 | 직접 써야 함 | let x: string |
TypeScript가 충분히 똑똑하기 때문에, 타입을 매번 쓸 필요는 없습니다. 단서가 충분할 때는 추론에 맡기고, 단서가 없을 때만 직접 알려주면 됩니다. 탐정에게 단서를 주면 알아서 해결합니다.
다음 챕터에서는 여러 값을 담는 자료구조인 배열과 튜플에 타입을 붙이는 방법을 살펴보겠습니다.