Skip to Content
WebTypeScriptTypeScript03. 기본 타입과 추론

이번 편의 결과물: models/expense.ts에 거래 필드를 원시 타입으로 정의하고, 하드코딩된 거래 1건이 화면에 출력됩니다. · 다루는 개념: 원시 타입, 타입 애너테이션과 타입 추론, 배열과 튜플, 리터럴 타입

이 편에서 만드는 파일

expense-tracker/src/ ├── models/ │ └── expense.ts (+) └── main.ts (~)

개념 정리

원시 타입

TypeScript의 기본 타입은 JavaScript의 원시 값 종류를 그대로 따릅니다.

타입예시 값
string'식비'
number12000
booleantrue
nullnull
undefinedundefined

타입 애너테이션과 타입 추론

변수 선언 뒤에 : 타입을 붙이는 것이 타입 애너테이션입니다. 초기값이 있으면 TypeScript가 그 값을 보고 타입을 스스로 알아내는데, 이것이 타입 추론입니다.

let count: number = 0 // 애너테이션 — 타입을 직접 명시 let price = 12000 // 추론 — TypeScript가 number로 판단

초기값만으로 타입이 분명하면 추론에 맡겨도 되지만, 함수 매개변수처럼 초기값이 없는 자리는 반드시 애너테이션이 필요합니다(04편에서 다룸). 이 편에서는 모델 파일의 의도를 분명히 남기기 위해 애너테이션을 명시합니다.

배열과 튜플

string[]처럼 쓰면 같은 타입의 값을 몇 개든 담을 수 있는 배열입니다. 반면 튜플은 길이와 각 위치의 타입이 고정된 배열입니다.

표기의미
string[]문자열이 몇 개든 들어갈 수 있는 배열
[string, number]정확히 2개, 첫 번째는 문자열·두 번째는 숫자로 고정된 튜플
[id: number, date: string]튜플에 이름표(label)를 붙여 각 자리의 의미를 표시

이름표는 타입 검사에 영향을 주지 않고, 편집기에서 각 자리의 의미를 보여주는 역할만 합니다.

리터럴 타입

string 타입은 아무 문자열이나 허용하지만, 리터럴 타입은 정확히 그 값 하나만 허용합니다.

let currencyA: string = 'KRW' // 어떤 문자열이든 나중에 대입 가능 let currencyB: 'KRW' = 'KRW' // 'KRW' 외에는 대입 불가능

실습

1. models/expense.ts 작성

// expense-tracker/src/models/expense.ts // 원시 타입 애너테이션 — 초기값이 있어 추론에 맡겨도 되지만, // 모델 파일에서는 각 필드의 타입을 명시적으로 남깁니다. export const sampleId: number = 1 export const sampleDate: string = '2026-09-20' export const sampleCategory: string = '식비' export const sampleAmount: number = 12000 export const sampleMemo: string = '점심 식사' // 리터럴 타입 — 'KRW' 한 값만 허용합니다. export const CURRENCY: 'KRW' = 'KRW' // 배열 타입 — 카테고리는 몇 개든 늘어날 수 있습니다. export const CATEGORIES: string[] = ['식비', '교통', '문화', '주거', '기타'] // 튜플 타입 — 순서와 각 자리 타입이 고정됩니다. 이름표로 의미를 표시합니다. export type ExpenseRow = [id: number, date: string, category: string, amount: number, memo: string] export const sampleExpenseRow: ExpenseRow = [sampleId, sampleDate, sampleCategory, sampleAmount, sampleMemo]

2. main.ts에서 화면에 출력

// expense-tracker/src/main.ts import './style.css' import { CATEGORIES, CURRENCY, sampleExpenseRow } from './models/expense.ts' function formatExpenseRow(row: typeof sampleExpenseRow): string { const [id, date, category, amount, memo] = row return `#${id} · ${date} · ${category} · ${amount.toLocaleString()}${CURRENCY} · ${memo}` } const app = document.querySelector<HTMLDivElement>('#app') if (app) { app.innerHTML = ` <main> <h1>가계부</h1> <p>사용 가능한 카테고리: ${CATEGORIES.join(', ')}</p> <ul> <li>${formatExpenseRow(sampleExpenseRow)}</li> </ul> </main> ` }

formatExpenseRow의 매개변수 타입을 typeof sampleExpenseRow로 쓰면, models/expense.ts가 만든 sampleExpenseRow와 정확히 같은 튜플 타입을 별도로 이름 붙이지 않고 재사용할 수 있습니다. 튜플을 const [id, date, category, amount, memo] = row로 구조 분해하면 각 변수가 원래 자리의 타입(number, string, string, number, string)을 그대로 받습니다.

3. 실행

npm run dev

확인

  • 화면에 “사용 가능한 카테고리: 식비, 교통, 문화, 주거, 기타”가 보입니다.
  • 목록에 “#1 · 2026-09-20 · 식비 · 12,000KRW · 점심 식사” 한 줄이 보입니다.
  • npx tsc --noEmit을 실행해도 오류가 없습니다.

직접 해보기

  1. CATEGORIES 배열에 새 카테고리(예: '의료')를 추가하고, 화면의 카테고리 목록에 바로 반영되는지 확인합니다.
  2. sampleExpenseRow의 네 번째 자리(금액)에 숫자 대신 문자열 '12000'을 넣어 보고, 편집기가 어떤 오류를 표시하는지 확인한 뒤 원래 값으로 되돌립니다.

정답 보기

ExpenseRow의 네 번째 자리는 amount: number로 고정되어 있으므로, 문자열 '12000'을 넣으면 “Type ‘string’ is not assignable to type ‘number’” 오류가 그 자리에 표시됩니다. 튜플은 값의 개수뿐 아니라 각 자리의 타입까지 고정한다는 것을 보여주는 예시입니다.

자주 하는 실수

증상원인고치는 법
튜플 값의 순서를 바꿨더니 오류가 남ExpenseRow는 자리마다 타입이 고정된 튜플이라 순서를 바꾸면 타입이 안 맞음정의한 순서(id, date, category, amount, memo)를 그대로 지킨다
CURRENCY에 다른 문자열을 대입하려다 오류가 남리터럴 타입 'KRW'는 그 값 하나만 허용함통화를 늘리려면 'KRW' | 'USD'처럼 유니온으로 바꿔야 한다(06편에서 다룸)
string[]Array<string>을 다른 타입으로 오해함둘은 같은 배열 타입을 쓰는 방식만 다른 표기법어느 쪽을 써도 동작은 같으며, 이 과목은 string[] 표기를 사용한다

확인 문제

문제 14지선다
타입 애너테이션과 타입 추론의 차이로 옳은 것은?
문제 24지선다
[id: number, date: string] 타입에 대한 설명으로 옳은 것은?
문제 34지선다
let currencyB: 'KRW' = 'KRW'처럼 선언했을 때 나중에 currencyB = 'USD'를 실행하면?
문제 44지선다
CATEGORIES: string[]에 대한 설명으로 옳은 것은?

참고 자료

Last updated on