类型错误:' post'指一个值,但在这里被用作类型。您的意思是' typeof post&#x27 ;?

发布于 2025-02-12 12:58:53 字数 8771 浏览 1 评论 0原文

我制作了一个具有NextJS + Sanity的博客应用程序,但我的[Slug] .TSX上有一个错误,

我会遇到错误:

类型错误:'post'是指一个值,但被用作类型 这里。您是说“ type of post”?

该文件具有.tsx扩展名,并且帖子接口在Typings.d.ts文件上声明。我在其他解决方案上阅读了我应该确保.tsx是扩展名而不是.ts,但这也指打字文件吗?因为我试图将.TS文件更改为.tsx,但它无法解决。

如果我将帖子更改为 typeof post 错误会消失,但是当调用邮政属性时会出现很多警告。

[slug] .tsx文件

import { GetStaticProps } from 'next'
import React, { useState } from 'react'
import Header from '../../components/Header'
import { sanityClient, urlFor } from '../../sanity'
import PortableText from 'react-portable-text'
import { useForm, SubmitHandler } from 'react-hook-form'

interface IFormInput {
  _id: string;
  name: string;
  email: string;
  comment: string;
}

interface Props {
    post: Post; 
}

export default function Post({ post }: Props) {

  const [submitted, setSubmitted] = useState(false);

    console.log(post);
    

  const { 
    register,
    handleSubmit, 
    formState: { errors } 
  } = useForm<IFormInput>()

  const onSubmit: SubmitHandler<IFormInput> = (data) => {
    fetch('/api/createComment', {
      method: 'POST',
      body: JSON.stringify(data),
    }).then(() => {
      console.log(data);
      setSubmitted(true);
    }).catch((err) => {
      console.log(err);
      setSubmitted(false);
    })
  };

  return (
    <main>
        <Header />

        <img 
          className='w-full h-40 object-cover' 
          src={urlFor(post.mainImage).url()!} 
          alt="" />

          <article className='max-w-3xl mx-auto p-5'>
            <h1 className='text-3xl mt-10 mb-3 font-extrabold text-[#292929] '>{post.title}</h1>
            <h2 className='text-xl font-light text-gray-500 mb-2'>{post.description}</h2>

            <div className='flex items-center space-x-2'>
              <img className='h-10 w-10 rounded-full' src={urlFor(post.author.image).url()!} alt="" />
              <p className='font-extralight text-sm'>
                Blog post by <span className='text-green-600'>{post.author.name}</span> - Published at {new Date(post._createdAt).toLocaleString()}
              </p>
            </div>

            <div className='mt-10'>
              <PortableText 
                className=''
                dataset={process.env.NEXT_PUBLIC_SANITY_DATASET!}
                projectId={process.env.NEXT_PUBLIC_SANITY_PROJECT_ID!}
                content={post.body}
                serializers={{ 
                  h1: (props: any) => (
                    <h1 className='text-2xl font-bold my-5' {...props} />
                  ),
                  h2: (props: any) => (
                    <h2 className='text-xl font-bold my-5' {...props} />
                  ),
                  li: ({ children }: any) => (
                    <li className='ml-4 list-disc'>{children}</li>
                  ),
                  link: ({ href, children }: any) => (
                    <a href={href} className='text-blue-500 hover:underline'>
                      {children}
                    </a>
                  ),
                 }}
              />
            
            </div>

          </article>

          <hr className='max-w-lg my-5 mx-auto border border-yellow-500' />

          {submitted ? (
              <div className='flex flex-col p-10 my-10 bg-yellow-500 text-white max-w-2xl mx-auto'>
                <h3 className='text-3xl font-bold'>
                  Thank you for submitting your comment!
                </h3>
                <p>Once it has been approved, it will appear below!</p>
              </div>
          ): (
<form onSubmit={handleSubmit(onSubmit)} className='flex flex-col p-5 max-w-2xl mx-auto mb-10' action="">
            <h3 className='text-sm text-yellow-500'>Enjoyed this article?</h3>
            <h4 className='text-3xl font-extrabold text-[#292929]'>Leave a comment below!</h4>
            <hr className='py-3 mt-2' />

            <input
                {...register("_id")}
                type="hidden"
                name="_id"
                value={post._id}
              />

            <label className='block mb-5'>
              <span className='text-gray-700'>Name</span>
              <input {...register("name", {required: true})} 
              className='shadow border rounded py-2 px-3 form-input mt-1 block w-full ring-yellow-500 focus:ring-1 focus:outline-none' type="text" name="name" placeholder='John Appleseed' />
            </label>
            <label className='block mb-5'>
              <span className='text-gray-700'>Email</span>
              <input {...register("email", {required: true})} 
              className='shadow border rounded py-2 px-3 form-input mt-1 block w-full ring-yellow-500 focus:ring-1 focus:outline-none' placeholder='John Appleseed' type="text" />
            </label>
            <label className='block mb-5'>
              <span className='text-gray-700'>Comment</span>
              <textarea {...register("comment", {required: true})}
              className='shadow border rounded py-2 px-3 mt-1 block w-full ring-yellow-500 focus:ring-1 focus:outline-none' placeholder='John Appleseed' rows={8} />
            </label>

            {/* errors will return when field validation fails */}

            <div className='flex flex-col p-5'>
              {errors.name && (<span className='text-red-500'>- The Name field is required</span>)}
              {errors.comment && (<span className='text-red-500'>- The Comment field is required</span>)}
              {errors.email && (<span className='text-red-500'>- The Email field is required</span>)}
            </div>

            <input className='shadow bg-yellow-500 hover:bg-yellow-400 transition-colors focus:shadow-outline focus:outline-none text-white font-bold py-2 px-4 rounded cursor-pointer' type="submit"  />
          </form>
          )}

          {/* Comments */}
          <div className='flex flex-col p-10 my-10 max-w-2xl mx-auto shadow-yellow-500 shadow space-y-2'>
            <h3 className='text-4xl font-extrabold text-[#292929]'>Comments</h3>
            <hr className='pb-2' />

            {post.comments.map((comment) => (
              <div key={comment._id}>
                <p><span className='text-yellow-500'>{comment.name}: </span>{comment.comment}</p>
              </div>
            ))}
          </div>
          
    </main>
  );
}

export const getStaticPaths = async () => {
    const query = `*[_type == "post"]{
        _id,
        slug {
          current
        }
      }`;

      const posts = await sanityClient.fetch(query);

      const paths = posts.map((post: Post) => ({
        params: {
            slug: post.slug.current,
        },
      }));

      return {
        paths,
        fallback: 'blocking',
      };
};

export const getStaticProps: GetStaticProps = async ({params}) => {
    const query = `*[_type == "post" && slug.current == $slug][0]{
      _id,
      _createdAt,
      title,
      author-> {
        name,
        image
      },
        'comments': *[
          _type == "comment" &&
          post._ref == ^._id &&
          approved == true],
      description,
      mainImage,
      slug,
      body
    }`

      const post = await sanityClient.fetch(query, {
        slug: params?.slug,
      });

      if (!post) {
        return {
            notFound: true
        }
      }

      return {
        props: {
            post,
        },
        revalidate: 60, // after 60s it will update the old cached version
      }
}

typings.d.ts file

export interface Post {
    _id: string;
    _createdAt: string;
    title: string;
    author: {
        name: string;
        image: string;
    };
    comments: Comment[];
    description: string;
    mainImage: {
        asset: {
            url: string;
        };
    };
    slug: {
        current: string;
    };
    body: [object];
}

export interface Comment {
    approved: boolean;
    comment: string;
    email: string;
    name: string;
    post: {
        _ref: string;
        _type: string;
    };
    _createdAt: string;
    _id: string;
    _rev: string;
    _type: string;
    _updatedAt: string;
}

I made a blog app with Nextjs + Sanity but I'm having an error on my [slug].tsx

I'm getting the error:

Type error: 'Post' refers to a value, but is being used as a type
here. Did you mean 'typeof Post'?

The file has the .tsx extension and Post interface is declared on a typings.d.ts file. I read on other solutions that I should make sure that .tsx is the extension instead of .ts but does that refer also to the typings file? Because I tried to change the .ts file into .tsx but it doesn't get solved.

If I change the Post to typeof Post error disappears but then a lot of warning appears when calling properties of Post.

[slug].tsx file

import { GetStaticProps } from 'next'
import React, { useState } from 'react'
import Header from '../../components/Header'
import { sanityClient, urlFor } from '../../sanity'
import PortableText from 'react-portable-text'
import { useForm, SubmitHandler } from 'react-hook-form'

interface IFormInput {
  _id: string;
  name: string;
  email: string;
  comment: string;
}

interface Props {
    post: Post; 
}

export default function Post({ post }: Props) {

  const [submitted, setSubmitted] = useState(false);

    console.log(post);
    

  const { 
    register,
    handleSubmit, 
    formState: { errors } 
  } = useForm<IFormInput>()

  const onSubmit: SubmitHandler<IFormInput> = (data) => {
    fetch('/api/createComment', {
      method: 'POST',
      body: JSON.stringify(data),
    }).then(() => {
      console.log(data);
      setSubmitted(true);
    }).catch((err) => {
      console.log(err);
      setSubmitted(false);
    })
  };

  return (
    <main>
        <Header />

        <img 
          className='w-full h-40 object-cover' 
          src={urlFor(post.mainImage).url()!} 
          alt="" />

          <article className='max-w-3xl mx-auto p-5'>
            <h1 className='text-3xl mt-10 mb-3 font-extrabold text-[#292929] '>{post.title}</h1>
            <h2 className='text-xl font-light text-gray-500 mb-2'>{post.description}</h2>

            <div className='flex items-center space-x-2'>
              <img className='h-10 w-10 rounded-full' src={urlFor(post.author.image).url()!} alt="" />
              <p className='font-extralight text-sm'>
                Blog post by <span className='text-green-600'>{post.author.name}</span> - Published at {new Date(post._createdAt).toLocaleString()}
              </p>
            </div>

            <div className='mt-10'>
              <PortableText 
                className=''
                dataset={process.env.NEXT_PUBLIC_SANITY_DATASET!}
                projectId={process.env.NEXT_PUBLIC_SANITY_PROJECT_ID!}
                content={post.body}
                serializers={{ 
                  h1: (props: any) => (
                    <h1 className='text-2xl font-bold my-5' {...props} />
                  ),
                  h2: (props: any) => (
                    <h2 className='text-xl font-bold my-5' {...props} />
                  ),
                  li: ({ children }: any) => (
                    <li className='ml-4 list-disc'>{children}</li>
                  ),
                  link: ({ href, children }: any) => (
                    <a href={href} className='text-blue-500 hover:underline'>
                      {children}
                    </a>
                  ),
                 }}
              />
            
            </div>

          </article>

          <hr className='max-w-lg my-5 mx-auto border border-yellow-500' />

          {submitted ? (
              <div className='flex flex-col p-10 my-10 bg-yellow-500 text-white max-w-2xl mx-auto'>
                <h3 className='text-3xl font-bold'>
                  Thank you for submitting your comment!
                </h3>
                <p>Once it has been approved, it will appear below!</p>
              </div>
          ): (
<form onSubmit={handleSubmit(onSubmit)} className='flex flex-col p-5 max-w-2xl mx-auto mb-10' action="">
            <h3 className='text-sm text-yellow-500'>Enjoyed this article?</h3>
            <h4 className='text-3xl font-extrabold text-[#292929]'>Leave a comment below!</h4>
            <hr className='py-3 mt-2' />

            <input
                {...register("_id")}
                type="hidden"
                name="_id"
                value={post._id}
              />

            <label className='block mb-5'>
              <span className='text-gray-700'>Name</span>
              <input {...register("name", {required: true})} 
              className='shadow border rounded py-2 px-3 form-input mt-1 block w-full ring-yellow-500 focus:ring-1 focus:outline-none' type="text" name="name" placeholder='John Appleseed' />
            </label>
            <label className='block mb-5'>
              <span className='text-gray-700'>Email</span>
              <input {...register("email", {required: true})} 
              className='shadow border rounded py-2 px-3 form-input mt-1 block w-full ring-yellow-500 focus:ring-1 focus:outline-none' placeholder='John Appleseed' type="text" />
            </label>
            <label className='block mb-5'>
              <span className='text-gray-700'>Comment</span>
              <textarea {...register("comment", {required: true})}
              className='shadow border rounded py-2 px-3 mt-1 block w-full ring-yellow-500 focus:ring-1 focus:outline-none' placeholder='John Appleseed' rows={8} />
            </label>

            {/* errors will return when field validation fails */}

            <div className='flex flex-col p-5'>
              {errors.name && (<span className='text-red-500'>- The Name field is required</span>)}
              {errors.comment && (<span className='text-red-500'>- The Comment field is required</span>)}
              {errors.email && (<span className='text-red-500'>- The Email field is required</span>)}
            </div>

            <input className='shadow bg-yellow-500 hover:bg-yellow-400 transition-colors focus:shadow-outline focus:outline-none text-white font-bold py-2 px-4 rounded cursor-pointer' type="submit"  />
          </form>
          )}

          {/* Comments */}
          <div className='flex flex-col p-10 my-10 max-w-2xl mx-auto shadow-yellow-500 shadow space-y-2'>
            <h3 className='text-4xl font-extrabold text-[#292929]'>Comments</h3>
            <hr className='pb-2' />

            {post.comments.map((comment) => (
              <div key={comment._id}>
                <p><span className='text-yellow-500'>{comment.name}: </span>{comment.comment}</p>
              </div>
            ))}
          </div>
          
    </main>
  );
}

export const getStaticPaths = async () => {
    const query = `*[_type == "post"]{
        _id,
        slug {
          current
        }
      }`;

      const posts = await sanityClient.fetch(query);

      const paths = posts.map((post: Post) => ({
        params: {
            slug: post.slug.current,
        },
      }));

      return {
        paths,
        fallback: 'blocking',
      };
};

export const getStaticProps: GetStaticProps = async ({params}) => {
    const query = `*[_type == "post" && slug.current == $slug][0]{
      _id,
      _createdAt,
      title,
      author-> {
        name,
        image
      },
        'comments': *[
          _type == "comment" &&
          post._ref == ^._id &&
          approved == true],
      description,
      mainImage,
      slug,
      body
    }`

      const post = await sanityClient.fetch(query, {
        slug: params?.slug,
      });

      if (!post) {
        return {
            notFound: true
        }
      }

      return {
        props: {
            post,
        },
        revalidate: 60, // after 60s it will update the old cached version
      }
}

typings.d.ts file

export interface Post {
    _id: string;
    _createdAt: string;
    title: string;
    author: {
        name: string;
        image: string;
    };
    comments: Comment[];
    description: string;
    mainImage: {
        asset: {
            url: string;
        };
    };
    slug: {
        current: string;
    };
    body: [object];
}

export interface Comment {
    approved: boolean;
    comment: string;
    email: string;
    name: string;
    post: {
        _ref: string;
        _type: string;
    };
    _createdAt: string;
    _id: string;
    _rev: string;
    _type: string;
    _updatedAt: string;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

痴情 2025-02-19 12:58:53

您拥有接口发布函数post()。我假设您想要接口道具中的前者,但是编译器和JS引擎会渗透后者。

重命名其中一个,以相同名称命名不同的事物很少是一个好主意。

You have interface Post and function Post(). I'm assuming you want the former in interface Props, but the compiler, and the JS engine, infers the latter.

Rename one of them, naming different things with the same name is rarely a good idea anyway.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文