4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

[TypeScript]trpcでDate型をサーバーとフロントでやり取りする方法

Last updated at Posted at 2023-04-05

TypeScriptのtrpc使ってますか? 僕はバリバリ使ってます。

サーバー側の処理で、DBから値を取得することがあると思います。
prismaやKnexで「DATETIME型」を取得すると、TypeScript側ではDate型として認識されます。

問題

問題は、trpcでサーバー側とフロント側の型を共有する場合です。
DATETIME型の値をサーバーからフロントへ送信した段階で、TypeScriptのDate型ではなくなります。
(YYYY-MM-DDTHH:mm:ss.sssZ の形式の、 ISOフォーマット(ISO 8601拡張フォーマット)の文字列となる)

そうすると、たとえばフロント側でYYYY年MM月DD日に変更したいとき、Date型と思って処理を行うと失敗することがあります。
Day.jsであれば、dayjs(dateValue)でISOStringだろうがDate型だろうがパースできるので大丈夫です。
しかし、date-fnsなどを使っているとDate型とISOString型で挙動が異なります。
そもそも関数の引数、返り値がstringなのかDateなのかは大きく変わってくるので、Date型で統一したいわけです。

import { format, parseISO } from "date-fns";
import dayjs from "dayjs";
// dayjsでYYYY-MM-DD HH:mm:ssに変換する場合は、stringでもDateでもDayjsにしてくれるのでいけるが
export const dayjsWrapperToYYYYMMDDHHmmss = (date: string | number | Date | dayjs.Dayjs) =>
  dayjs().format("YYYY-MM-DD HH:mm:ss");

// date-fnsでyyyy-MM-dd HH:mm:ssに変換する
// Date型なら成功するが、ISOStringだと失敗する。ISOString型の場合はparseISOが必要。
export const dateFnsWrapperToYYYYMMDDHHmmss = (date: Date) => format(date, "yyyy-MM-dd HH:mm:ss");

どうすれば良いのか

trpcのtransformerという機能を使います。
https://trpc.io/docs/server/data-transformers

事前にsuperjsonというライブラリを追加しておきましょ。

npm i superjson

サーバー側の最低限の実装

server.ts
import { initTRPC } from "@trpc/server";
import superjson from "superjson";

export const t = initTRPC.create({
  transformer: superjson, //ここに足してあげる
});

export const appRouter = t.router({
  getToday: t.procedure.query(() => new Date()),
});

export type AppRouter = typeof appRouter;

フロント側の実装

import "./App.css";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { httpBatchLink } from "@trpc/client";
import { useState } from "react";
import superjson from "superjson";
import { trpc } from "./utils/trpc";
import { IndexPage } from "./pages/IndexPage";

export const App = () => {
  const [queryClient] = useState(() => new QueryClient());
  const [trpcClient] = useState(() =>
    trpc.createClient({
      links: [
        httpBatchLink({
          url: "http://localhost:22004/trpc",
        }),
      ],
      transformer: superjson, //ここに足す!
    })
  );
  return (
    <trpc.Provider client={trpcClient} queryClient={queryClient}>
      <QueryClientProvider client={queryClient}>
        <IndexPage />
      </QueryClientProvider>
    </trpc.Provider>
  );
};

これで無事にDate型のデータをやり取りできるようになります。
スクリーンショット 2023-04-05 22.30.07.png

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?