添加TypeScript支持
import { json } from "@remix-run/node";
import { Link, useLoaderData } from "@remix-run/react";
type Post = {
  slug: string;
  title: string;
};
type LoaderData = {
  posts: Array<Post>;
};
export const loader = async () => {
  return json<LoaderData>({
    posts: [
      {
        slug: "my-first-post",
        title: "My First Post",
      },
      {
        slug: "90s-mixtape",
        title: "A Mixtape I Made Just For You",
      },
    ],
  });
};
export default function Posts() {
  const { posts } = useLoaderData() as LoaderData;
  return (
    <main>
      <h1>Posts</h1>
      <ul>
        {posts.map((post) => (
          <li key={post.slug}>
            <Link
              to={post.slug}
              className="text-blue-600 underline"
            >
              {post.title}
            </Link>
          </li>
        ))}
      </ul>
    </main>
  );
}
在json里添加了一个LoaderData的接口
这部分Ts还是比较简单的,有兴趣自己查查
但是如果在useLoaderData后边不设置 as LoaderData就会出现any类型
所以我们在读取数据的时候又设置了一下any
补充
在loader里的json函数是为了在响应数据的时候创建一个application/json头,并假定你使用了utf-8编码
关于这部分可以参考代码
const json = (data, init = {}) => {
  let responseInit = typeof init === "number" ? {
    status: init
  } : init;
  let headers = new Headers(responseInit.headers);
  if (!headers.has("Content-Type")) {
    headers.set("Content-Type", "application/json; charset=utf-8");
  }
  return new Response(JSON.stringify(data), { ...responseInit,
    headers
  });
};
补充完毕
当设置好TS类型后,即使通过网络请求读取数据,也可以获得类型的安全性,因为在同一个文件定义,除非在读取数据的时候崩溃,否则在组件和API中都具有类型安全性。
一点点的重构
一个可靠的办法就是创建一个处理特定问题的模块,在例子中,将阅读和攥写帖子,现在让我们新建一个模块,然后增加getPosts函数,并将他导出
创建app/models/post.server.ts
粘贴内容
type Post = {
  slug: string;
  title: string;
};
export async function getPosts(): Promise<Array<Post>> {
  return [
    {
      slug: "my-first-post",
      title: "My First Post",
    },
    {
      slug: "90s-mixtape",
      title: "A Mixtape I Made Just For You",
    },
  ];
}
这里虽然没有使用任何异步,但是使用了async,说明以后你可以在这里使用
因为async返回Promise,所以类型提示是
Promise<Array<Post>>
接下来在
app\routes\posts\index.tsx
更新代码为
import { getPosts } from "~/models/post.server";
type LoaderData = {
  // this is a handy way to say: "posts is whatever type getPosts resolves to"
  posts: Awaited<ReturnType<typeof getPosts>>;
};
export const loader = async () => {
  return json<LoaderData>({
    posts: await getPosts(),
  });
};
这里的
 Awaited<ReturnType<typeof getPosts>>
算是一个难点
getPosts是一个函数
首席按typeof获取他的类型
得到
()=>Promise<Post[]>
然后使用ReturnType得到一个函数的返回类型推断
也就是Promise<Post[]>
Awaited类似于await,会递归取得嵌套在promise的类型
可以参考https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html
也就是说最后得到了Post[]作为返回类型
那么说白了
type LoaderData = {
  // this is a handy way to say: "posts is whatever type getPosts resolves to"
  posts: Awaited<ReturnType<typeof getPosts>>;
};
这段代码
也就是
type LoaderData = {
  posts: Post[];
};
罢了
那官方课程第一篇的一半已经结束后,后续涉及Prisma~
结语
撒花~