router loader typescript

GI JUNG·2024년 2월 6일
0

react

목록 보기
8/8
post-thumbnail

react-router tutorial을 typescript로 마이그레이션 하면서 loader에 대한 type을 어떻게 지정하고 그에 대한 데이터를 typescript가 어떻게 추론하게 할 수 있는지에 대한 장벽에 막혔었다.

문제를 여기fredericoo라는 분의 솔루션을 통해 해결할 수 있었다.

🍀 loader type 정의

useLoaderData를 통해 가져온 data에 대한 type을 추론시키기 위해서 loader의 type을 정의해주어야 한다.

fredericoo 분의 loader를 정의한 type이다.

import { LoaderFunction } from 'react-router-dom';

export type LoaderData<TLoaderFn extends LoaderFunction> = Awaited<ReturnType<TLoaderFn>> extends Response | infer D
	? D
	: never;

처음에는 이해 안 가는 부분이 있었지만, 차근히 뜯어보면 알 수 있다.

  • LoaderData<TLoaderFn extends LoaderFunction> : 인자로 받는 함수는 LoaderFunction을 확장 해야 한다.
  • Awaited<ReturnType<TLoaderFn>> extends Response : 인자로 받는 함수의 return type이 Response 객체를 확장 한다면 Promise<Response>가 LoaderData type으로 확정 된다.
  • infer D ? D : never : 인자로 받는 함수의 return type이 Response를 확장하지 않을 때 type의 평가가 이뤄지는 구문으로 Promise가 아닐 때 타입을 추론한다.
    • 타입이 추론 될 때 ⇒ D = Promise type으로 확정
    • 타입이 추론되지 않을 때 ⇒ never type으로 확정

따라서, 배운 내용을 적용하면 아래와 같이 된다.

import { LoaderFunction, useLoaderData } from "react-router-dom";
import { createContact, getContacts } from "../contacts";

type LoaderData<TLoaderFunc extends LoaderFunction> = Awaited<
  ReturnType<TLoaderFunc>
> extends Response | infer D
  ? D
  : never;

type Contact = {
  id: string;
  createdAt: Date;
  first: string;
  last: string;
  avatar: string;
  twitter: string;
  notes: string;
  favorite: boolean;
};

export const loader = (async (): Promise<{ contacts: Contact[] }> => {
  const contacts = await getContacts();
  return { contacts };
}) satisfies LoaderFunction;

export default function Root() {
  // const { contact } = useLoaderData() as { contact: Contact[] };
  const { contacts } = useLoaderData() as LoaderData<typeof loader>;
	
	return (...//)
}

이제 contact를 잘 추론하는지 확인해보자

contact의 type을 잘 추론하는 것을 볼 수 있다.

간편하게 const { contacts } = useLoaderData() as { contacts: Contact[] };와 같이 해도 상관없을 것 같다. 하지만, 오류는 짐작할 수 없기에 나는 자세하게 type을 지정하는 것을 선호한다.

또한 이러한 과정 없이 빠르게 개발하고 싶은 사람은 이 문제의 솔루션을 제공한 사람이 만든 react-router-typesafe를 설치해서 사용해도 좋을 것 같다.

📚 참고

react-router-dom-typescript
loader type definition github

profile
step by step

0개의 댓글