그동안 배운 타입스크립트 문법으로 간단한 투두 리스트를 구현해보기로 하였다. 구현하면서 배우지 못한 문법도 추가로 작성할 예정이며, 기본적인 템플릿은 AI로 생성했다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="styles.css" />
<title>Todo App</title>
</head>
<body>
<div class="todo-container">
<h1>Todo App</h1>
<input type="text" id="taskInput" placeholder="할 일 추가" />
<button id="addTask">추가</button>
<ul id="taskList">
<!-- 동적으로 추가할 내용 -->
</ul>
</div>
<script src="app.js"></script>
</body>
</html>
input
button
ul
태그의 요소를 가져온다.type Task = {
id: number;
text: string;
completed: boolean;
};
코드를 구조화하고, 유지보수를 쉽게 하기 위하여 객체로 생성했다. id
는 고유 식별자, text
는 내용, completed
는 완료 여부 속성이다.
const tasks: Task[] = [];
Tasks
객체를 담는 배열. 추가한 리스트를 관리한다.
const taskInput = document.getElementById('taskInput') as HTMLInputElement;
const addTaskButton = document.getElementById('addTask') as HTMLButtonElement;
const taskList = document.getElementById('taskList') as HTMLUListElement;
HTML에서 taskInput
addTaskButton
taskList
요소를 가져온다. taskInput은 할 일을 입력하는 입력 필드, addTaskButton은 할 일을 추가하는 버튼, taskList는 할 일 목록을 표시하는 <ul>
요소를 나타낸다.
as 키워드
let title = document.querySelector('#title');
title.innerHTML = 'Hi'
타입스크립트는 위와 같이 작성하면 에러를 발생시킨다. title
변수의 타입이 HTMLElement | null
이기 때문에 타입 확정이 불가능한 상태에서 DOM 조작을 금지시킨다.
따라서 Type Narrowing 또는 Type Assertion을 통해 타입을 확정시킨다. as
키워드는 Type Assertion으로 사용되며 컴파일러에게 "이 변수는 이러한 타입이다" 라고 명시해준다.
// 할 일 추가 함수
function addTask() {
const text = taskInput.value.trim();
if (!text) return;
const newTask: Task = {
id: tasks.length + 1,
text,
completed: false,
};
tasks.push(newTask);
taskInput.value = '';
renderTask(newTask);
}
addTask
함수는 사용자가 input 태그에 입력한 값을 가져오고, 새로운 Task 객체를 만든다음에 tasks 배열에 푸시한다. 그리고 나서 input 태그 필드를 비우고, 렌더링하는 함수인 renderTask를 실행한다.
function renderTask(task: Task) {
const taskItem = document.createElement('li');
taskItem.innerHTML = `
<input type="checkbox" id="task-${task.id}" ${task.completed ? 'checked' : ''}>
<label for="task-${task.id}">${task.text}</label>
`;
taskList.appendChild(taskItem);
}
// 할 일 추가 버튼 클릭 이벤트 처리
addTaskButton.addEventListener('click', addTask);
renderTask
함수는 li
요소를 생성하고 Task 객체를 HTML 목록으로 렌더링한다. 이후 추가 버튼에 이벤트 리스너를 추가해서 버튼을 클릭했을 때 addTask 함수가 실행되도록 추가한다.
// app.ts
// Task 타입 정의
type Task = {
id: number;
text: string;
completed: boolean;
};
// 할 일 목록
const tasks: Task[] = [];
// HTML 요소 가져오기
const taskInput = document.getElementById('taskInput') as HTMLInputElement;
const addTaskButton = document.getElementById('addTask') as HTMLButtonElement;
const taskList = document.getElementById('taskList') as HTMLUListElement;
// 할 일 추가 함수
function addTask() {
const text = taskInput.value.trim();
if (!text) return;
const newTask: Task = {
id: tasks.length + 1,
text,
completed: false,
};
tasks.push(newTask);
taskInput.value = '';
renderTask(newTask);
}
// 할 일 렌더링 함수
function renderTask(task: Task) {
const taskItem = document.createElement('li');
taskItem.innerHTML = `
<input type="checkbox" id="task-${task.id}" ${task.completed ? 'checked' : ''}>
<label for="task-${task.id}">${task.text}</label>
`;
taskList.appendChild(taskItem);
}
// 할 일 추가 버튼 클릭 이벤트 처리
addTaskButton.addEventListener('click', addTask);