✍️ What I Learned/TIL

[TIL] TypeScript로 투두리스트 만들기 - global.d.ts, 이벤트 타입지정

Jiwon() 2023. 7. 28. 23:13


1. global.d.ts

Todo List를 만들 때, Todo 객체는 여러 컴포넌트에서 쓰일 것이므로 Todo 객체의 타입은 전역적으로 설정해주면 효율적일 것이다.

  • `global.d.ts` 파일은 TypeScript에서 전역으로 사용할 타입들을 선언하는 파일이다.
  • 일반적으로 `.d.ts` 확장자를 가진 파일들은 TypeScript 타입 선언 파일로서, 프로젝트 전체에서 사용되는 타입들을 정의하기 위해 사용된다.

 

1) 내가 작성한 global.d.ts 파일

// global.d.ts
import { Dispatch, SetStateAction } from "react";

export interface Todo {
  id: string;
  title: string;
  content: string;
  isDone: boolean;
}

export interface TodosProps {
  todos: Todo[];
  setTodos: Dispatch<SetStateAction<Todo[]>>;
}

보통 타입 선언 파일에서는 `declare` 키워드를 이용해서 타입을 선언한다고 하는데, `declare`로 선언해주고 작업을 진행하니 계속해서 오류가 발생하여 `declare`를 빼고 그냥 export 해주었다.

 

2) declare

  • `declare` 키워드는 주로 외부 모듈이나 라이브러리의 타입 선언을 지정하는데 사용된다.
  • 따라서 `declare` 키워드는 내부 모듈이나 파일에서 사용하지 않아야 한다.
  • 나는 현재 내부 컴포넌트들에서만 Todo와 TodoProps의 타입을 사용하고 있기 때문에 declare로 선언해주면 안되는 것이다.

 

3) 내부 모듈과 외부 모듈?

  • 내용을 찾아서 읽어보았으나 아직 잘 이해가 가지 않는다. 아래 링크에 자세히 설명되어있으니, 나중에 다시 반복해서 읽어볼 것
타입스크립트 모듈 & 네임스페이스 시스템 이해하기

 

 


2. 이벤트 타입지정

1) 내가 작성한 AddTodo.tsx 파일

// AddTodo.tsx
import React, { useState } from "react";
import { Todo, TodosProps } from "components/config/global";
import shortid from "shortid";
import { styled } from "styled-components";

const AddTodo = ({ todos, setTodos }: TodosProps) => {
  const initialState = { id: shortid(), title: "", content: "", isDone: false };
  const [todo, setTodo] = useState(initialState);

  // 이벤트 타입 지정
  const onChange = (e: React.FormEvent<HTMLInputElement>) => {
    const { name, value } = e.currentTarget;
    setTodo({ ...todo, [name]: value });
  }

  const onSubmit = (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    setTodos([...todos, { ...todo, id: shortid() }]);
    setTodo(initialState);
  }

  return (
    <>
      <StAddFormWrapper>
        <StAddForm onSubmit={onSubmit}>
          <StAddHeader>
            <h2>Add</h2>
            <StAddBtn>+</StAddBtn>
          </StAddHeader>
          <StInputTitle
            name="title"
            value={todo.title}
            onChange={onChange}
            placeholder="제목을 입력하세요."
            required
          />
          <StInputContent
            name="content"
            value={todo.content}
            onChange={onChange}
            placeholder="내용을 입력하세요."
            required
          />
        </StAddForm>
      </StAddFormWrapper>
    </>
  );
};

export default AddTodo;

const StAddFormWrapper = styled.div`
  width: 80%;
  height: 10vh;
  position: absolute;
  bottom: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
`;

const StAddForm = styled.form`
  display: flex;
  flex-direction: column;
  justify-content: center;
`

const StAddHeader = styled.div`
  display: flex;
  justify-content: space-between;
`

const StAddBtn = styled.button`
  outline: none;
  border: none;
  background-color: none;
  font-size: 18px;
  font-weight: 700;
`

const StInputTitle = styled.input`
  height: 25px;
  outline: none;
  border: none;
  border-bottom: 1px solid gray;
`;

const StInputContent = styled.input`
  height: 25px;outline: none;
  border: none;
  border-bottom: 1px solid gray;
`

 

  • `e: React.FormEvent<HTMLInputElement>`, `e: React.FormEvent<HTMLFormElement>`는 React에서 이벤트 핸들러 함수를 정의할 때 사용하는 타입이다.
    • e: 이벤트 객체 (Event Object)
    • React.MouseEvent: 마우스 이벤트를 나타내는 타입
    • <HTMLInputElement>: 이벤트가 발생하는 엘리먼트의 타입. 여기서는 <input>에서 발생한 이벤트를 처리하므로 HTMLInputElement로 지정된다.
  • 따라서 e: React.MouseEvent<HTMLButtonElement>는 버튼 엘리먼트에서 발생한 마우스 이벤트 객체를 나타낸다. 이벤트 핸들러 함수 내에서 이벤트 객체를 사용하여 버튼 클릭과 같은 동작을 처리할 수 있다.

 

참고 블로그 - [typescript] 타입스크립에서 이벤트 객체 타입 지정하기

 

 

 

2) SyntheticEvent (합성 이벤트)

이벤트 핸들러는 모든 브라우저에서 이벤트를 동일하게 처리하기 위한 이벤트 래퍼 SyntheticEvent 객체를 전달받는다.

 

  • Keyboard Events
    • ex) onKeyDown, onKeyPress, onKeyUp
  • Focus Events
    • ex) onFocus, onBlur
  • Form Events
    • ex) onSubmit, onChange, onInput, onInvalid, onReset
  • Generic Events
    • ex) onError, onLoad
자세한 내용 참고 - SyntheticEvent - React