React
TypeScript
- 리액트와 타입스크립트를 함께 사용하다보면 이벤트 타입을 정의해줘야 하는 순간이 온다.
- 사실 타입스크립트를 사용하다 보면 생각보다 타입 지정을 요구하는 경우가 드물다는 것을 느낀다.
- 하지만 요소에서 발생하는 이벤트를 다루려면 높은 확률로 타입을 지정해줘야 한다.
- 기존에는 필요할 때마다
input, button...
등의 요소에서 발생하는 타입을 찾아서 작성하였다. - 이번에 이벤트 타입에 대해서 더 찾아보며 알게된 것들을 정리하고자 한다.
EventHandler, Event
- 계속 헷갈렸던 개념인데, 쉽게 생각해
EventHandler
는 함수를 정의할 때,Event
는 실제 이벤트가 발생한 객체를 정의할 때 사용된다.
1
2
3
4
5
6
7
const clickHandler:MouseEventHandler<HTMLButtonElement> = () => {
...
}
const clickHandler = (e:MouseEvent<HTMLButtonElement>) => {
...
}
이벤트 타입 확인하기
MouseEvent, ChangeEvent...
등 이벤트를 확인할 때 Ctrl + 클릭을 사용하거나,node_modules/@types/react/ts
에 들어가보면 여러가지 이벤트를 확인할 수 있다.- 여기서 다양한 타입을 확인할 수 있는데 좋은 자료가 있어서 가져왔다.
- 버튼 컴포넌트를 만든다고 했을 때,
onClick
이라는 함수를props
로 받는다고 가정하자.
1
2
3
4
5
6
7
8
9
10
11
12
13
interface Props {
onClick(): void;
}
function Button({ onClick }: Props) {
return <button onClick={onClick}>클릭 이벤트</button>;
}
function App() {
function onClick(e: React.MouseEvent) {}
return <Button onClick={onClick} />;
}
- 이렇게 작성된 코드의
onClick
함수의 타입은 매개변수에 대한 타입을 별도로 지정하지 않았기 떄문에 타입 에러가 발생한다.
1
Type '(e: MouseEvent<Element, MouseEvent>) => void' is not assignable to type '() => void'.
타입 추론하기
- 타입 에러에 대한 구문만 보고도 유추하여 작성할 수 있지만, 위의
@types
파일을 좀 더 파헤쳐보기로 한다. - 우선 마우스 이벤트 핸들러가 지정된 타입을 찾는다.
- 여기서 사용되는
Element
는 우리가 사용할 요소가 되며,HTMLButtonElement
를 뜻한다. - 이것을 풀어서 설명해보자면
EventHandler
는MouseEvent
구문과 같게 작성할 수 있다.
1
2
3
4
5
type MouseEventHandler<T = Element> = EventHandler<MouseEvent<T>>;
=== // 이 두 가지 코드는 동일하다.
type MouseEventHandler<HTMLButtomElement> = EventHandler<MouseEvnet<HTMLButtomElement>>;
- 마우스 이벤트 핸들러와 관련된 코드는 아래와 같다.
1
2
3
4
5
6
7
type MouseEventHandler<T = Element> = EventHandler<MouseEvent<T>>;
interface MouseEvent<T = Element, E = NativeMouseEvent> extends UIEvent<T, E> {}
type EventHandler<E extends SyntheticEvent<any>> = {
bivarianceHack(event: E): void;
}["bivarianceHack"];
MouseEventHandler
는 기본적으로Element
를 매개변수로 받을 수 있으며,EventHandler
는Element
를 매개변수로 받는MouseEvent
를 매개변수로 받을 수 있다.MouseEvent
는Element
와NativeMouseEvent
를 매개변수로 받으며,UIEvent
와 마우스 이벤트 간에 공통 속성을 상속받는다.SyntheticEvent
는 합성 이벤트로, 리액트에서 이벤트 시스템과 호환되도록 만들어지는 객체이다.bivarianceHack
이라는 속성을 가진 객체는 아래의 정보로 bivarianceHack 이란
좀 더 간편하게 이벤트 사용하기
- 나는 매번
MouseEvent
인지 다른 이벤트인지 헷갈린다. - 이벤트 핸들러 타입과
HTMLElement
를 매번 떠올려야 하는 번거로움이 있는데props
로 이를 해결하는 방법이 있다.
1
2
3
4
5
6
7
8
9
import {ComponentProps} from "react";
function Component(){
const handleChange : ComponentProps<'input'>['onChange'] = (e) => {
...
}
return <input onChange={handlerChange}/>;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import { ComponentProps, DOMAttributes } from 'react';
type EventHandlers<T> = Omit<
DOMAttributes<T>,
'children' | 'dangerouslySetInnerHTML'
>;
export type Event<
TElement extends keyof JSX.IntrinsicElements,
TEventHandler extends keyof EventHandlers<TElement>
> = ComponentProps<TElement>[TEventHandler];
function Component() {
const handleChange: Event<'input', 'onChange'> = (e) => {
console.log(e.target.value);
};
return <input onChange={handleChange} />;
}