李恒道 发表于 2022-11-27 18:36:02

【Remix教程翻译】开发者博客(二)

# 添加TypeScript支持
```javascript
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编码
关于这部分可以参考代码
```javascript
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
粘贴内容
```javascript
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,所以类型提示是
```javascript
Promise<Array<Post>>
```
接下来在
app\routes\posts\index.tsx
更新代码为
```javascript
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~
# 结语
撒花~





页: [1]
查看完整版本: 【Remix教程翻译】开发者博客(二)