Passing Typescript interface props to a child component returns not existing properties

Issue

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} />

Solution

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>
);

Answered By – T.J. Crowder

Answer Checked By – Senaida (AngularFixing Volunteer)

Leave a Reply

Your email address will not be published.