Home > Software design >  Passing Typescript interface props to a child component returns not existing properties
Passing Typescript interface props to a child component returns not existing properties

Time:03-18

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 && (
  • Related