TypeScript를 직접 프로젝트에 적용해보니 아직 정리가 되지 않을 부분들도 있었고 쉽게 적용되지가 않았다. React에서 TypeScript를 적용할때 많이 쓰는 타입들과 사용방법에 대해서 정리해보자!
기본 타입
number, string, boolean: 기본 데이터 타입으로 상태(State),Props의 속성의 타입으로 정의할 때 사용한다.
null, undefined, void: 값이 없음을 나타낼때 사용하는 타입이다.
객체와 인터페이스
interface: 객체의 구조를 타입으로 정의하는데 사용한다.
type: 객체 타입을 정의하는데 사용되며, 유니온, 인터섹션 타입 정의에 사용한다.
interface Student {
id: number;
name: string;
}
// 유니온 타입: 여러 타입 중 하나가 될 수 있는 값을 나타냄
type User {
id: number;
name: string;
}
type Student {
id: number;
Subject: string;
}
type UserInfo = User | Student
// 인터섹션 타입: 여러 타입을 결합하여 하나의 타입으로 만들 때 사용
type User {
id: number;
name: string;
}
type UserProfile {
age: number;
image: string;
}
type User & UserProfile
함수의 매개변수와 반환값에 대한 타입을 정의할 때 사용한다.
type Calculator = (a: number, b: number) => number;
const add: Calculator = (a, b) => a + b;
// 선택적 매개변수: 선택적으로 매개변수를 받을 수 있으며 기본값을 설정할 수 있다.
type Greetings = (name: string, greeting?: string) => string;
const greet: GreetingFunction = (name, greeting = "Hello") => {
return `${greeting}, ${name}!`;
};
// 오버로드된 함수 타입: 하나의 함수에 대해 다른 함수 형태를 가질 수 있다. 함수가 다른 매개변수 형식 또는 반환값 형식에 따라 다르게 동작할 때 사용된다.
type PrintValue = {
(value: number): void;
(value: string): void;
};
const printValue: PrintValue = (value) => {
console.log(value);
};
printValue(123);
printValue("Hello World");
React 컴포넌트의 이벤트 핸들러를 타입으로 정의할 때 사용한다.
React.MouseEvent, React.KeyboardEvent, React.FormEvent, React.EventHandler가 있다.
// React.MouseEvent 타입: 마우스 이벤트를 다룰 때 사용하며, 주로 onClick, onMouseDown, onMouseUp, onMouseMove 등의 이벤트에 사용된다.
type MouseClickHandler = (event: React.MouseEvent<HTMLButtonElement>) => void;
const handleClick: MouseClickHandler = (event) => {
console.log(event.clientX, event.clientY);
};
<button onClick={handleClick}>Click Me</button>;
// React.KeyboardEvent 타입: 키보드 이벤트를 다룰 때 사용되며, onKeyDown, onKeyUp, onKeyPress 등의 이벤트에 사용된다.
type KeyPressHandler = (event: React.KeyboardEvent<HTMLInputElement>) => void;
const handleKeyPress: KeyPressHandler = (event) => {
if (event.key === 'Enter') {
console.log('Enter key pressed!');
}
};
<input type="text" onKeyPress={handleKeyPress} placeholder="텍스트를 입력해주세요" />;
//React.FormEvent 타입: 폼 요소에서 발생하는 이벤트를 다룰 때 사용되며, 주로 onSubmit, onChange 등에 사용된다.
type FormSubmitHandler = (event: React.FormEvent<HTMLFormElement>) => void;
export default function MyForm() {
const [text, setText] = useState<string>('');
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setText(event.target.value);
};
const handleSubmit: FormSubmitHandler = (event) => {
event.preventDefault();
console.log('Form submitted', text);
};
return (
<form onSubmit={handleSubmit}>
<input
type="text"
placeholder="텍스트를 입력해주세요"
value={text}
onChange={handleChange}
/>
<button type="submit">Submit</button>
</form>
);
};
리덕스(Redux)와 같은 상태 관리 라이브러리에서 액션과 상태 타입을 정의할 때 사용할 수 있다.
Redux
// 액션(Action) 타입
const ADD_TODO = 'ADD_TODO';
const DELETE_TODO = 'DELETE_TODO';
// 액션 생성자(Action Creator)
function addTodo(text: string) {
return {
type: ADD_TODO,
text,
};
}
function deleteTodo(text: string) {
return {
type: DELETE_TODO,
text,
};
}
// 상태(State) 타입
interface User {
id: number;
name: string;
}
interface TodoState {
todos: Todo[];
user: User | null;
}
type TodoAction = {
type: typeof ADD_TODO | typeof DELETE_TODO;
text: string;
};
// 리듀서(Reducer)
const initialTodoState: TodoState = {
todos: [],
user: null,
};
function todosReducer(state: TodoState = initialTodoState, action: TodoAction): TodoState {
switch (action.type) {
case ADD_TODO:
return {
...state,
todos: [...state.todos, { text: action.text, completed: false }],
};
case DELETE_TODO:
return {
...state,
todos: state.todos.filter((todo) => todo.text !== action.text),
};
default:
return state;
}
}
Context API
import { createContext, useContext, useState } from 'react';
const TodoContext = createContext<Todo[]>([]);
const TodoProvider: React.FC = ({ children }) => {
const [todos, setTodos] = useState<Todo[]>([]);
return (
<TodoContext.Provider value={todos}>
{children}
</TodoContext.Provider>
);
};
ref를 사용하여 DOM 요소에 접근할 때, 해당 요소의 타입을 지정할 수 있다.
import React, { useRef } from 'react';
export default function MypageInput () {
const inputRef = useRef<HTMLInputElement>(null);
const focusInput = () => {
if (inputRef.current) {
inputRef.current.focus();
}
};
return (
<div>
<input ref={inputRef} />
<button onClick={focusInput}>Click Me!</button>
</div>
);
};
React.FC를 사용하여 컴포넌트의 함수 타입을 정의하고, Props 타입으로 컴포넌트의 속성 타입을 정의한다.
interface Props {
name: string;
age: number;
}
export default function UserContent ({ name, age }:Props) {
return (
<div>
<p>Name: {name}</p>
<p>Age: {age}</p>
</div>
);
};
컴포넌트 내에서 조건부로 렌더링할 때 사용하는 타입이다
interface ToggleDisplayProps {
show: boolean;
children: React.ReactNode;
}
export default function ToggleDisplay ({ show, children }:ToggleDisplayProps) {
return show ? <div>{children}</div> : null;
};
React Router와 함께 사용할 때 라우트와 URL 매개변수의 타입을 정의한다.
import { RouteComponentProps } from 'react-router-dom';
interface MatchParams {
id: string;
}
export default function UserProfile({ match }: RouteComponentProps) {
const userId = match.params.id;
// ...
}