You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript:如何转换Promise返回的API对象(Next.js 13 Fetch)

解决方案

1. 修正工具方法的查询与类型转换

当前getPost函数存在两个核心问题:一是查询语句未使用传入的slug参数,会返回所有文章而非目标单篇;二是Sanity返回的日期为字符串格式,需要转为Date类型,同时要确保返回结果与Post类型结构匹配。

修改后的工具方法:

export async function getPost(slug: string): Promise<Post> {
  // 通过slug过滤目标文章,仅返回单个结果
  const postData = await SanityClient.fetch(`
    *[_type == "post" && slug.current == $slug][0]
  `, { slug }); // 将slug参数传入查询语句

  if (!postData) {
    throw new Error(`未找到slug为"${slug}"的文章`);
  }

  // 手动转换类型,处理日期字段并确保嵌套结构匹配
  return {
    ...postData,
    publish_date: new Date(postData.publish_date),
    banner_image: postData.banner_image,
    category: postData.category || [],
    author: postData.author || [],
    body: postData.body || []
  } as Post;
}

2. 修正页面中的调用逻辑

App Router 场景(Next.js 13+)

页面组件可直接声明为异步组件,在组件内部调用工具方法获取数据:

// app/post/[slug]/page.tsx
async function PostPage() {
  const post = await getPost('test-post');

  return (
    <div>
      <h1>{post.title}</h1>
      <p>{post.headline}</p>
      {/* 渲染其他Post属性 */}
    </div>
  );
}

export default PostPage;

Pages Router 场景

使用getStaticProps或getServerSideProps预获取数据:

// pages/post/[slug].tsx
export async function getStaticProps({ params }: { params: { slug: string } }) {
  const post = await getPost(params.slug);

  return {
    props: { post }
  };
}

function PostPage({ post }: { post: Post }) {
  return (
    <div>
      <h1>{post.title}</h1>
      <p>{post.headline}</p>
    </div>
  );
}

export default PostPage;

3. 增强类型安全(可选)

若要严格校验返回数据的结构,可创建类型守卫函数:

function isPost(data: unknown): data is Post {
  const post = data as Post;
  return (
    typeof post.title === 'string' &&
    typeof post.headline === 'string' &&
    typeof post.slug === 'string' &&
    post.publish_date instanceof Date &&
    Array.isArray(post.category) &&
    Array.isArray(post.author) &&
    Array.isArray(post.body)
  );
}

// 在getPost中使用类型守卫
export async function getPost(slug: string): Promise<Post> {
  const postData = await SanityClient.fetch(`
    *[_type == "post" && slug.current == $slug][0]
  `, { slug });

  if (!isPost(postData)) {
    throw new Error('返回的文章数据结构不匹配');
  }

  return postData;
}

内容的提问来源于stack exchange,提问作者Don

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 18:33:25