This package is a replacement for superjson to use in your Remix app

Overview

remix-typedjson

All Contributors

This package is a replacement for superjson to use in your Remix app. It handles a subset of types that superjson supports, but is faster and smaller.

NOTE: Although faster, remix-typedjson is nowhere near as flexible as superjson. It only supports a subset of types with no extensibility. If you need the advanced features of superjson, then I definitely recommend it.

Example site: https://remix-typedjson-example-production.up.railway.app/

Example repo: https://github.com/kiliman/remix-typedjson-example

The following types are supported:

  • Date
  • BigInt
  • Set
  • Map
  • RegExp
  • undefined
  • Error
  • NaN
  • Number.POSITIVE_INFINITY
  • Number.NEGATIVE_INFINITY

🚧 Work In Progress

Sets and Maps currently only support string keys and JSON serializable values. Complex types coming soon.

🛠 How to Use with Remix

In order to get full-type fidelity and type inference, you must be on Remix v1.6.5+. You will also need to import the following replacement functions.

typedjson

Replacement for Remix json helper. It also supports the optional ResponseInit, so you can return headers, etc.

Make sure your loader and action use the new declaration format:

 export const loader: LoaderFunction = async ({request}) => {}
 export const loader = async ({request}: LoaderArgs) => {}
 export async function loader({request}: LoaderArgs) {}

Usage

return typedjson(
  { greeting: 'hello', today: new Date() },
  // ResponseInit is optional, just like the `json` helper
  { headers: { 'set-header': await commitSession(session) } },
)

useTypedLoaderData

Replacement for Remix useLoaderData. Use the generic to get the correct type inference.

Usage

const loaderData = useTypedLoaderData<typeof loader>()

useTypedActionData

Replacement for Remix useActionData. Use the generic to get the correct type inference.

Usage

const actionData = useTypedActionData<typeof action>()

useTypedFetcher

Replacement for Remix useFetcher. Use the generic to get the correct type inference for the fetcher.data property.

Usage

const fetcher = useTypedFetcher<typeof action>()
fetcher.data // data property is fully typed

redirect

In order to return a redirect, you will need to import the redirect function from this package, in order for the type inference to work properly.

However, you can also throw redirect() and you can use the original redirect function from Remix.

😍 Contributors

Thanks goes to these wonderful people (emoji key):


Kiliman

💻 📖

Kent C. Dodds

💻

Simon Knott

💻 🐛 ⚠️

Tony Truand

💻 ⚠️

This project follows the all-contributors specification. Contributions of any kind welcome!

Comments
  • `useTypedLoaderData` Syntax Error during another Error

    `useTypedLoaderData` Syntax Error during another Error

    Trying to reproduce with a minimal example:

    export const loader = async ({
        request,
      }: LoaderArgs): Promise<TypedJsonResponse<LoaderData>> => {
      
        const data = {
          date: new Date()
        };
      
        return typedjson(data);
    };
    
    
    export default function Dashboard(): JSX.Element {
      const loaderData = useTypedLoaderData<typeof loader>();
      const { date } = loaderData;
      // Purposefully throw an error to show issue
      throw new Error("TEST")
      return null;
    }
    
    

    Error message in browser console window:

    Uncaught SyntaxError: Unexpected identifier 'Nov'
    

    When checking the file its talking about in Sources tab You'll see something like this in the file:

    'routeData':{'routes/dashboard': {'date':Thu Nov 03 2022 11:04:25 GMT-0400 (Eastern Daylight Time)}}'
    

    Seems like the typedjson is causing syntax errors somewhere due to the type conversions?

    opened by jmaldon1 7
  • Error: Cannot find module 'tslib'

    Error: Cannot find module 'tslib'

    I am testing a deployment to fly.io and am getting an error:

    [info] > start
    [info] > cross-env NODE_ENV=production node ./build/server.js
    [info] Error: Cannot find module 'tslib'
    [info] Require stack:
    [info] - /myapp/node_modules/remix-typedjson/dist/remix.js
    [info] - /myapp/node_modules/remix-typedjson/dist/index.js
    [info] - /myapp/build/index.js
    [info] - /myapp/build/server.js
    [info] at Function.Module._resolveFilename (node:internal/modules/cjs/loader:956:15)
    [info] at Function.Module._load (node:internal/modules/cjs/loader:804:27)
    [info] at Module.require (node:internal/modules/cjs/loader:1028:19)
    [info] at require (node:internal/modules/cjs/helpers:102:18)
    [info] at Object.<anonymous> (/myapp/node_modules/remix-typedjson/dist/remix.js:4:17)
    [info] at Module._compile (node:internal/modules/cjs/loader:1126:14)
    [info] at Object.Module._extensions..js (node:internal/modules/cjs/loader:1180:10)
    [info] at Module.load (node:internal/modules/cjs/loader:1004:32)
    [info] at Function.Module._load (node:internal/modules/cjs/loader:839:12)
    [info] at Module.require (node:internal/modules/cjs/loader:1028:19)
    

    I noticed your tsconfig.json has importHelpers set to true. https://github.com/kiliman/remix-typedjson/blob/c1ed8747d60cd651be689fc1eb327f4a00701f81/tsconfig.json#L13

    Are consumers responsible for also installing tslib, or is there a better way to resolve this error?

    opened by ryanwoodcox 7
  • 🔨 Export `UseDataFunctionReturn` & `RemixSerializedType` types

    🔨 Export `UseDataFunctionReturn` & `RemixSerializedType` types

    Related to conversation https://github.com/kiliman/remix-typedjson/issues/18 - exports the UseDataFunctionReturn type which makes typing a loader response when consumed via useMatches and should be helpful in concert with the useRouteLoaderData function.

    opened by lukebowerman 6
  • Error on remix 1.7.0

    Error on remix 1.7.0

    Upon installing remix 1.7.0 I started having this issue with remix-typedjson:

    Error: You must render this element in a remix route element
    [dev:*server]     at invariant (/Users/.../app/node_modules/@remix-run/react/dist/invariant.js:15:11)
    [dev:*server]     at useRemixRouteContext (/Users/.../app/node_modules/@remix-run/react/dist/components.js:179:3)
    [dev:*server]     at useLoaderData (/Users/.../app/node_modules/@remix-run/react/dist/components.js:964:10)
    [dev:*server]     at useTypedLoaderData (/Users/.../app/node_modules/remix-typedjson/dist/remix.js:20:44)
    [dev:*server]     at App (/Users/.../app/src/app/root.tsx:58:29)
    [dev:*server]     at renderWithHooks (/Users/.../app/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:5662:16)
    [dev:*server]     at renderIndeterminateComponent (/Users/.../app/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:5735:15)
    [dev:*server]     at renderElement (/Users/.../app/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:5950:7)
    [dev:*server]     at renderNodeDestructiveImpl (/Users/.../app/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:6108:11)
    [dev:*server]     at renderNodeDestructive (/Users/.../app/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js:6080:14)
    
    opened by fernandoabolafio 6
  • `useMatches` type inference

    `useMatches` type inference

    I found myself wanting to access a loader response generated by remix-typedjson via useMatches and ran into difficulty trying to specify the type of the data attribute.

    I tried doing various incantations of:

    match as Awaited<Promise<ReturnType<typeof loader>>>
    

    In so doing I was never able to get the typedJson unwrapped from the response type, the closest I managed to get was:

    Response & { typedjson(): Promise<{ foo: string, bar: number }> }
    

    When Remix 1.10 lands useRouteLoaderData (https://reactrouter.com/en/main/hooks/use-route-loader-data) seems like it'll offer a better model for accessing loader data from elsewhere in the tree much more elegantly than the useMatches route so perhaps I'm barking up the wrong tree entirely.

    opened by lukebowerman 4
  • export TypedFetcherWithComponents type

    export TypedFetcherWithComponents type

    Exporting the TypedFetcherWithComponents comes handy, when you would like to pass around a fetcher in react components and you would like to type those components.

    Also, it's exported in the remix-react base package as well.

    opened by joelazar 4
  • Could we make this lib work with Cloudflare Workers platform?

    Could we make this lib work with Cloudflare Workers platform?

    When I use remix-typedjson with Remix + Cloudflare Workers template, there is the following error:

    Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
    1. You might have mismatching versions of React and the renderer (such as React DOM)
    2. You might be breaking the Rules of Hooks
    3. You might have more than one copy of React in the same app
    See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
    TypeError: Cannot read properties of null (reading 'useContext')
    
    opened by supachaidev 4
  • Problem with deep objects

    Problem with deep objects

    When I wrap the loader data in another object, it fails while deserializing. Here's a reproduction: https://stackblitz.com/edit/github-gbcwza?file=app%2Froutes%2Ftest.tsx

    The code:

      return typedjson(
        { data: { greeting: "hello", today: new Date() } },
      );
    
    opened by frontsideair 4
  • Add option to serialize custom data types

    Add option to serialize custom data types

    Awesome project!

    I would like to serialize DateTime (from luxon), inbuilt URL data type etc. For reference, I am using https://github.com/clentfort/urql-custom-scalars-exchange to serialize the data in loader.

    opened by IgnisDa 2
  • Problem with deep object and a shallow value

    Problem with deep object and a shallow value

    Sorry to be the bearer of the bad news, but I may have stumbled upon another bug. This is the payload:

      return typedjson(
        { data: [{ greeting: "hello", today: new Date() }], counter: 1 },
      );
    

    And the StackBlitz link: https://stackblitz.com/edit/github-gbcwza-6tcdt7?file=app%2Froutes%2Ftest.tsx

    counter is null and its meta is "undefined". Doesn't change when it's a string either.

    opened by frontsideair 2
  • Is it possible to have data parameter typed in meta function export?

    Is it possible to have data parameter typed in meta function export?

    Firstly, thank you for the awesome library and for bringing end-to-end type safety to Remix.

    I have a problem that is specific to the exported meta function from a route.

    Have a posts/$slug route which has a loader which exports few posts and rendered markdown in html format. With remix-typedjson it looks something like this:

    export const loader = async ({ params }: LoaderArgs) => {
      invariant(params.slug, "params.slug is required")
    
      const post = await getPost(params.slug)
    
      invariant(post, `Post not found: ${params.slug}`)
    
      const html = marked(post.markdown)
    
      return typedjson({
        post,
        html,
      })
    }
    

    But when I want to access the returned data in the meta function to add a title for my page, I obviously don't get the types as MetaFunction by default has data set to any:

    export const meta: MetaFunction = ({ data }) => {
      console.log("Data:", data)
    
      return {
        title: `Posts | ${data.post.title}`,
      }
    }
    

    Is it possible to type data returned from loader in the meta function?

    opened by shripadk 1
Owner
Michael Carter
Michael Carter
Hemsida för personer i Sverige som kan och vill erbjuda boende till människor på flykt

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: np

null 4 May 3, 2022
Kurs-repo för kursen Webbserver och Databaser

Webbserver och databaser This repository is meant for CME students to access exercises and codealongs that happen throughout the course. I hope you wi

null 14 Jan 3, 2023
Remix enables you to build fantastic user experiences for the web and feel happy with the code that got you there. In this workshop, we'll look at some more advanced use cases when building Remix applications.

?? Advanced Remix Workshop Remix enables you to build fantastic user experiences for the web and feel happy with the code that got you there. In this

Frontend Masters 167 Dec 9, 2022
The Remix version of the fakebooks app demonstrated on https://remix.run. Check out the CRA version: https://github.com/kentcdodds/fakebooks-cra

Remix Fakebooks App This is a (very) simple implementation of the fakebooks mock app demonstrated on remix.run. There is no database, but there is an

Kent C. Dodds 61 Dec 22, 2022
simple-remix-blog is a blog template built using Remix and TailwindCSS. Create your own blog in just a few minutes!

simple-remix-blog is a blog template built using remix.run and TailwindCSS. It supports markdown and MDX for the blog posts. You can clone it and star

José Miguel Álvarez Vañó 8 Dec 8, 2022
This package enables you to mount your Remix app at a different path than root

Remix Mount Routes This package enables you to mount your Remix app at a different path than root. ?? Installation > npm install -D remix-mount-routes

Kiliman 26 Dec 17, 2022
Package fetcher is a bot messenger which gather npm packages by uploading either a json file (package.json) or a picture representing package.json. To continue...

package-fetcher Ce projet contient un boilerplate pour un bot messenger et l'executable Windows ngrok qui va permettre de créer un tunnel https pour c

AILI Fida Aliotti Christino 2 Mar 29, 2022
Remix Stack for deploying to Vercel with remix-auth, Planetscale, Radix UI, TailwindCSS, formatting, linting etc. Written in Typescript.

Remix Synthwave Stack Learn more about Remix Stacks. npx create-remix --template ilangorajagopal/synthwave-stack What's in the stack Vercel deploymen

Ilango 56 Dec 25, 2022
Remix enables you to build fantastic user experiences for the web and feel happy with the code that got you there. Get a jumpstart on Remix with this workshop.

?? Remix Fundamentals Build Better websites with Remix Remix enables you to build fantastic user experiences for the web and feel happy with the code

Frontend Masters 204 Dec 25, 2022
A devtool improve your pakage manager use experience no more care about what package manager is this repo use; one line, try all.

pi A devtool improve your pakage manager use experience no more care about what package manager is this repo use; one line, try all. Stargazers over t

tick 11 Nov 1, 2022
A Cypress plugin that generates test scripts from your interactions, a replacement Cypress Studio for Cypress v10 🖱 ⌨

DeploySentinel Cypress Recorder Plugin Create Cypress tests scripts within the Cypress test browser by simply interacting with your application, simil

DeploySentinel 13 Dec 15, 2022
Metamask replacement for your E2E tests.

Headless Web3 Provider Metamask replacement for your E2E tests. Why "headless"? Because it doesn't have a visual interface, reject (or accept) transac

Emil Ibatullin 6 Dec 13, 2022
A lightweight, standalone package to integrate full PWA features into Remix 💿

Remix PWA PWA integration & support for Remix Remix PWA is a lightweight, standalone npm package that adds full Progressive Web App support to Remix ?

Abdur-Rahman 220 Jan 3, 2023
Automatic arxiv->ar5iv link replacement in Chrome.

Automatic arxiv->ar5iv link replacement in Chrome. This chrome extension will automatically replace arxiv.org/pdf/* links with ar5iv links for more we

yobi byte 44 Oct 29, 2022
Replacement for comma.ai backend and useradmin dashboard

Replacement for comma.ai backend and useradmin dashboard. Bundled with a modified version of comma's cabana to allow viewing & analyzing drives.

null 15 Jan 1, 2023
A Hackable Markdown Note Application for Programmers. Version control, AI completion, mind map, documents encryption, code snippet running, integrated terminal, chart embedding, HTML applets, plug-in, and macro replacement.

Yank Note A hackable markdown note application for programmers Download | Try it Online >>> Not ecommended English | 中文说明 [toc]{level: [2]} Highlights

洋子 4.3k Dec 31, 2022
A drop in replacement for Hacker News with support for dark mode and more.

Worker News A drop in replacement for Hacker News with support for dark mode, quotes in comments, user identicons and submission favicons. What's cool

Worker Tools 18 Dec 31, 2022
A Drop-in Jalali Replacement for filament DateTimePicker

Filament Jalali Date Time Picker Field This package is a Drop-in replacement for DatePicker and DateTimePicker field type you just need to replace tho

AriaieBOY 8 Dec 3, 2022
Pretty, customisable, cross browser replacement scrollbars

jScrollPane - cross browser custom scroll bars jScrollPane is a jQuery plugin which allows you to replace a browser's default scroll bars (on an eleme

Kelvin Luck 2.2k Dec 15, 2022