I understand how to assign prop types using TypeScript. But I am not able to pass down the interface prop checking down to another component.
Error:
Property 'comments' does not exist on type 'ArticleProps'.ts(2339)
Tried adding it but still no luck. Thought that If you are inside the parent component that if you create a component and pass the data that it would work the same, but TypeScript obviously doesn't like this.
export interface ArticleProps {
page: {
_id: string;
_createdAt: string;
comments: Comment[];
body: any;
publishedAt: string;
title: string;
featuredImage: {
asset?: string;
alt?: string;
};
author: {
name: string;
featuredImage: {
alt?: string;
};
};
};
}
export interface Comment {
name: string;
approved: boolean;
comment: string;
email: string;
article: {
_ref: string;
_type: string;
};
_createdAt: string;
_id: string;
_rev: string;
_type: string;
_updatedAt: string;
}
Comments.tsx:
import { dateFormat } from "@lib/helpers";
import { Comment, ArticleProps } from "types/article";
import { FC } from "react";
const Comments: FC<ArticleProps> = ({ comments }: ArticleProps) => (
<>
{comments.length > 0 && (
<div className="flex flex-col my-10">
<h3 className="text-4xl">Comments</h3>
<hr className="mt-2 mb-5 border-2 border-yellow-500" />
{comments.map(({ name, _id, _createdAt, comment }: Comment) => (
<div className="px-4 py-6 bg-white rounded-sm shadow-md" key={_id}>
<p>
<time className="block text-sm font-bold">
{dateFormat(_createdAt)}
</time>
<span className="text-bubblegum">{name}</span> :
<span className="pl-2">{comment}</span>
</p>
</div>
))}
</div>
)}
</>
);
export default Comments;
index.tsx:
{/* Comments */}
<Comments comments={comments} />
CodePudding user response:
ArticleProps
doesn't have a comments
property. It has a page
property that has a comments
property, but it doesn't have its own comments
property.
If you want Comments
to receive the comments that would be on an ArticleProps
instance (as you seem to from your usage <Comments comments={comments} />
), you could define that like this:
const Comments: FC<{comments: Comment[]}> = ({ comments }) => (
or without FC
(some say it's not best practice):
const Comments = ({ comments }: {comments: Comment[]}) => (
Instead of Comment[]
there, you could use ArticleProps["page"]["comments"]
so that the type would follow the type of comments
on page
of ArticleProps
.
Sometimes that's appropriate, but it seems overkill in that example.
const Comments: FC<{comments: ArticleProps["page"]["comments"]}> = ({ comments }) => (
// or without `FC`:
const Comments = ({ comments }: {comments: ArticleProps["page"]["comments"]}) => (
Or Pick<ArticleProps["page"], "comments">
:
const Comments: FC<Pick<ArticleProps["page"], "comments">> = ({ comments }) => (
<div>{comments}</div>
);
// or without `FC`:
const Comments = ({ comments }: Pick<ArticleProps["page"], "comments">) => (
<div>{comments}</div>
);
CodePudding user response:
Property 'comments' does not exist on type 'ArticleProps'.ts(2339)
That's because comments
is declared in ArticleProps.page
:
export interface ArticleProps {
page: {
...
comments: ...
Try this:
({ page }: ArticleProps) => (
<>
{page.comments.length > 0 && (