TypeScriptでRemixのuseLoaderDataを使うと困るのがJsonifyObject型が返ってくること。
JsonifyObjectが返却されてコンポーネントで使うとタイプエラー・・、は多くの人が経験あるのではないでしょうか。
型の不一致が起きてしまうと都合が悪いので、remix-typedjsonを使って本来の型でデータを取得する方法を紹介します。
remix-typedjsonとは?
remix-typedjsonは、Remixアプリケーションで使用するためのsuperjsonの代替パッケージです。superjsonがサポートする型のサブセットを扱いつつ、より高速で、サイズも小さいのが特徴です。
https://github.com/kiliman/remix-typedjson
そもそもsuperjsonとは、JSONにはない追加の型(例えば、日付、正規表現、マップ、セットなど)をサポートすることで、JavaScriptのデータをより豊富にシリアライズおよびデシリアライズできるようにするライブラリです。
superjsonを使用することで、開発者はJSONで直接サポートされていないデータ型を扱う際の多くの制限を克服でき、アプリケーション間でのデータの受け渡しがより柔軟でエラーが少なくなります。
https://github.com/blitz-js/superjson
@remix-runを使った場合
まずはremix-typedjsonを使わずに@remix-runを使った場合です。
useLoaderDataを使うとJsonifyObject型が返ってきます。
import { json } from '@remix-run/node'
import { useLoaderData } from '@remix-run/react'
export async function loader() {
return json({
user: {
id: 1,
name: 'CodeConnect',
},
})
}
export default function Index() {
const { user } = useLoaderData<typeof loader>()
// userの型
// JsonifyObject<{
// id: number
// name: string
// }>
}
JsonifyObject型に対しての対応方法
もしJsoninfyObjectを使って良ければ対応する方法もあります。
本来の型ではタイプエラーになってしまうのでSerializeFromを使います 。
import { SerializeFrom } from '@remix-run/node'
interface Props {
user: SerializeFrom<{
id: number
name: string
}>
}
SerializeFromを使うことでJsonifyObject型でラップされた型を取得することができます。
remix-typedjsonを使った場合
次にこの記事の本題、remix-typedjsonを使った方法です。
まずはremix-typedjsonをインストールします。
yarn add remix-typedjson
remix-typedjsonを使うと、loaderの返り値にJsonifyObjectを使わずに型を指定できます。
jsonメソッドの代わりにtypedjson、useLoaderDataの代わりにuseTypedLoaderDataを使います。
import { typedjson, useTypedLoaderData } from 'remix-typedjson'
export async function loader() {
return typedjson({
user: {
id: 1,
name: 'CodeConnect',
},
})
}
export default function Index() {
const { user } = useTypedLoaderData<typeof loader>()
// userの型
// {
// id: number
// name: string
// }
}
これでJsonifyObject型にはならずSerializeFormを使う必要もなくなります。
まとめ
普通にRemixで実装していくと、絶対にこの問題にぶち当たるんじゃない?というくらいJsonifyObject型にはまります。
remix-typedjsonは公式のパッケージではないので、絶対に使うのを推奨とは言えません。
メリットとデメリットを考えたうえでremix-typedjsonの使用を検討されてみてはいかがでしょうか。