쉽게 시작하는 타입스크립트: 2 - 투두앱 타입 정의하기

Bumgu·2024년 1월 21일
0
let todoItems;

// api
function fetchTodoItems() {
  const todos = [
    { id: 1, title: '안녕', done: false },
    { id: 2, title: '타입', done: false },
    { id: 3, title: '스크립트', done: false },
  ];
  return todos;
}

// crud methods
function fetchTodos() {
  const todos = fetchTodoItems();
  return todos;
}

function addTodo(todo) {
  todoItems.push(todo);
}

function deleteTodo(index) {
  todoItems.splice(index, 1);
}

function completeTodo(index, todo) {
  todo.done = true;
  todoItems.splice(index, 1, todo);
}

// business logic
function logFirstTodo() {
  return todoItems[0];
}

function showCompleted() {
  return todoItems.filter(item => item.done);
}


function addTwoTodoItems() {

}


function log() {
  console.log(todoItems);
}

todoItems = fetchTodoItems();
addTwoTodoItems();
log();

이런 투두앱 코드가있습니다.
코드블럭으로 볼 땐 아무 문제가 없지만 IDE를 통해 열게 되면

any타입이니 사용에 따라 맞는 타입을 정의 해주라는 경고문구가 뜹니다. 이부분들을 고쳐보겠습니다.

1.타입 정의해주기

1. fetchTodoItems()

fetchTodoItems()를 먼저 고쳐보겠습니다.

function fetchTodoItems() {
  const todos = [
    { id: 1, title: '안녕', done: false },
    { id: 2, title: '타입', done: false },
    { id: 3, title: '스크립트', done: false },
  ];
  return todos;
}

todos를 반환하는데 todos는 객체를 요소로 가진 배열입니다.
그렇기 때문에 { id: number; title: string; doen: boolean }[]
을 반환타입으로 지정합니다. 이는 number, string, boolean타입의 객체를 가진 배열 임을 명시합니다.

function fetchTodoItems(): { id: number; title: string; doen: boolean }[] {
  const todos = [
    { id: 1, title: '안녕', done: false },
    { id: 2, title: '타입', done: false },
    { id: 3, title: '스크립트', done: false },
  ];
  return todos;
}

2. fetchTodos()

function fetchTodos() {
  const todos = fetchTodoItems();
  return todos;
}

fetchTodoItems()의 반환값을 받아와 반환해줍니다. fetchTodoItems()는 객체를 가진 배열을 반환하기에 이 함수도 똑같이 붙여줍니다.

function fetchTodos(): { id: number; title: string; done: boolean }[] {
  const todos = fetchTodoItems();
  return todos;
}

3. let todoItems

todoItems는 맨 윗줄에 아무런값을 할당하지 않고 선언했습니다.
addTodo()를 보면 todo를 인자로 넘겨 todoItems변수에 push해주기 때문에 객체를 가진 배열이 추가된다는것을 알 수 있습니다. 그렇기에 같은 타입을 정의해줍니다.

let todoItems: { id: number; title: string; done: boolean }[];

4. addTodo()

addTodo()의 파라미터는 todo객체를 받습니다. 그렇기에 todo타입을 지정해주도록 하겠습니다. 하지만 배열 을 추가하는것이 아닌 객체를 추가하기 때문에 []는 필요가 없습니다.

function addTodo(todo: { id: number; title: string; done: boolean }) {
  todoItems.push(todo);
}

1번,2번은 반환값이 있어서 반환타입을 지정해줬는데 이 함수는 반환값이 없습니다. 그럼 어떤 타입을 지정해줘야 할까요? 자바에서 반환값이 없다면 public void로 메소드를 선언하듯 타입스크립트에서도 void를 반환타입으로 지정해주면 됩니다.

function addTodo(todo: { id: number; title: string; done: boolean }): void {
  todoItems.push(todo);
}

5. deleteTodo()

splice를 이용해 지정된 부분을 자릅니다. splice 인자는 숫자이기 때문에 파라미터 타입은 number로 지정하고, 반환값이 없기 때문에 void를 지정해줍니다.

function deleteTodo(index: number): void {
  todoItems.splice(index, 1);
}

6. completeTodo()

tododone속성을 트루로 바꿔주고 splice의 세번째 인자를 이용해 요소를 수정해줍니다.

function completeTodo(index: number, todo: { id: number; title: string; done: boolean }): void {
  todo.done = true;
  todoItems.splice(index, 1, todo);
}

index는 숫자를 받고 todo는 투두 데이터이기에 number와 투두타입을 지정합니다.

7. logFirstTodo()

todoItems의 첫번째 요소를 반환해줍니다. todoItems는 객체를 가진 배열이고 첫번째 요소는 당연히 투두타입의 객체 일것입니다.

function logFirstTodo(): { id: number; title: string; done: boolean } {
  return todoItems[0];
}

그렇기에 반환타입을 투두타입으로 지정해줬습니다.

8. showCompleted()

showCompleted()는 완료한 목록을 반환합니다. 이는 객체를 가진 배열을 반환해준다는걸 알 수 있습니다.

function showCompleted(): { id: number; title: string; done: boolean }[] {
  return todoItems.filter(item => item.done);
}

배열을 반환하기에 []를 붙여주어야 합니다.

9. addTwoTodoItems()

addTwoTodoItems()는 아직 구현되어있지 않습니다. 구현해주고 타입역시 지정해주도록 하겠습니다.

function addTwoTodoItems(): void {
  addTodo({ id: 4, title: '블로그 글쓰기', done: false})
  addTodo({ id: 5, title: '코드 짜기', done: false})
}

addTodo()를 사용해 두개의 데이터를 넣어줍니다. 반환값이 없기 때문에 void타입을 반환값으로 지정해줍니다.

이제 타입은 모두 정해주었습니다.
하지만 코드를 보면 { id: 4, title: '블로그 글쓰기', done: false}가 여러번 반복이 되는걸 알 수 있습니다. 한 두번이면 상관없지만 여러번 사용하기에 힘들고 코드가 길어져 가독성이 떨어집니다. 인터페이스를 사용해 이를 보완할 수 있습니다.

2. 인터페이스로 반복되는 타입 줄이기

코드의 맨 위에 인터페이스를 선언합니다.

interface Todo {
	id: number;
    title: string;
    done: boolean;
}

이 인터페이스는 id, title, done속성을 갖는 객체 타입을 의미합니다. 앞서 써왔던
{ id: 4, title: '블로그 글쓰기', done: false} 를 정의해놨기 때문에 이 코드들을

function fetchTodos(): { id: number; title: string; done: boolean }[] {
  const todos = fetchTodoItems();
  return todos;
}
function fetchTodos(): Todo[] {
  const todos = fetchTodoItems();
  return todos;
}

이런식으로 줄일 수 있습니다. 배열타입이기 때문에 []를 사용해 Todo타입의 배열을 반환값으로 지정해줄 수 있습니다. 인터페이스를 사용해 코드를 완성한 최종입니다.

3. 최종 코드

interface Todo {
  id: number;
  title: string;
  done: boolean;
}

let todoItems: Todo[];


// api
function fetchTodoItems(): Todo[] {
  const todos = [
    { id: 1, title: '안녕', done: false },
    { id: 2, title: '타입', done: false },
    { id: 3, title: '스크립트', done: false },
  ];
  return todos;
}

// crud methods
function fetchTodos(): Todo[] {
  const todos = fetchTodoItems();
  return todos;
}

function addTodo(todo: Todo): void {
  todoItems.push(todo);
}

function deleteTodo(index: number): void {
  todoItems.splice(index, 1);
}

function completeTodo(
  index: number,
  todo: Todo
): void {
  todo.done = true;
  todoItems.splice(index, 1, todo);
}

// business logic
function logFirstTodo(): Todo {
  return todoItems[0];
}

function showCompleted(): Todo[] {
  return todoItems.filter(item => item.done);
}


function addTwoTodoItems(): void {
  addTodo({ id: 4, title: '블로그 글쓰기', done: false});
  addTodo({ id: 5, title: '코드짜기', done: false});
}


function log() {
  console.log(todoItems);
}

todoItems = fetchTodoItems();
addTwoTodoItems();
log();

파라미터와 반환값의 타입을 정해주고, 인터페이스를 사용해 코드를 짧게 줄여보았습니다.
이상 이번 포스팅을 마치겠습니다. 감사합니다.

profile
Software VS Me

0개의 댓글