examples
examples copied to clipboard
Typecheck fails on blog-tutorial example
When I run typechecking or have my editor open, the following errors are shown by typescript, even on a fresh clone of the example:
> typecheck
> tsc -b && tsc -b cypress
app/routes/notes/$noteId.tsx:36:16 - error TS2352: Conversion of type 'SerializeObject<Simplify<{ note: Note; } & {}>>' to
type 'LoaderData' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, conv
ert the expression to 'unknown' first.
The types of 'note.createdAt' are incompatible between these types.
Type 'string' is not comparable to type 'Date'.
36 const data = useLoaderData() as LoaderData;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
app/routes/posts/$slug.tsx:23:26 - error TS2352: Conversion of type 'SerializeObject<Simplify<{ post: Post; html: string; }
& {}>>' to type 'LoaderData' may be a mistake because neither type sufficiently overlaps with the other. If this was inten
tional, convert the expression to 'unknown' first.
The types of 'post.createdAt' are incompatible between these types.
Type 'string' is not comparable to type 'Date'.
23 const { post, html } = useLoaderData() as LoaderData;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
app/routes/posts/admin.tsx:16:21 - error TS2352: Conversion of type 'SerializeObject<Simplify<{ posts: Post[]; } & {}>>' to
type 'LoaderData' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, con
vert the expression to 'unknown' first.
Types of property 'posts' are incompatible.
Type 'SerializeObject<Simplify<{ createdAt: Date; updatedAt: Date; title: string; slug: string; markdown: string; } & {
}>>[]' is not comparable to type 'Post[]'.
Type 'SerializeObject<Simplify<{ createdAt: Date; updatedAt: Date; title: string; slug: string; markdown: string; } &
{}>>' is not comparable to type 'Post'.
16 const { posts } = useLoaderData() as LoaderData;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
app/routes/posts/index.tsx:18:21 - error TS2352: Conversion of type 'SerializeObject<Simplify<{ posts: Post[]; } & {}>>' to
type 'LoaderData' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, con
vert the expression to 'unknown' first.
Types of property 'posts' are incompatible.
Type 'SerializeObject<Simplify<{ createdAt: Date; updatedAt: Date; title: string; slug: string; markdown: string; } & {
}>>[]' is not comparable to type 'Post[]'.
18 const { posts } = useLoaderData() as LoaderData;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Found 4 errors.
What seems to be happening is that createdAt is a string rather than a date somewhere in between (in Prisma, maybe). A temporary workaround is to convert the result of useLoaderData to unknown and then LoaderData, but this isn't the best solution. This problem happens regardless of the TS version (both 4.7 and 4.8 result in an error). Is there a known solution to this?
It's always difficult to keep a tutorial updated with the latest changes (especially on a fast-paced project like Remix).
The "current" recommended approach to typing loaders is as follows:
- use
LoaderArgsinstead ofLoaderFunction - always wrap return value in
jsonhelper - use
useLoaderArgs<typeof loader>()instead ofas LoaderData
import { json, type LoaderArgs } from '@remix-run/node'
import { db } from '~/db.server'
export const loader = async ({request, params}: LoaderArgs => {
const { jokeId } = params
const joke = await db.joke.findUnique({
where: { id: jokeId },
})
return json({joke})
}
export default function Joke() {
const { joke } = useLoaderData<typeof loader>()
return <div>{ joke.name }</div>
}
NOTE: Since Remix always returns loader data as serialized JSON, values like
Datewill be converted to a string. So the inferred type will bystringnotDate. If you would like to maintain the native types, then you can useremix-typedjsonwhich will maintain the native types across the entire request.
https://github.com/kiliman/remix-typedjson
@PythonCreator27 I'm currently working on a PR that will update these old usages to the newly recommended one
It would be great if has a codemod to update all the examples
@franklinjavier I thought about creating a codemod for this, but since it has so many edge-cases that aren't straight-forward, it's better to do it manually yourself in each codebase
@franklinjavier I thought about creating a codemod for this, but since it has so many edge-cases that aren't straight-forward, it's better to do it manually yourself in each codebase
agree