Norayr Ghukasyan
Norayr Ghukasyan

Reputation: 1418

functional React components with TypeScript using generic props

I am trying to understand and solve my own problem which is related to react components generic props.I have taken this code example from this article functional React components with TypeScript using generic props. Unfortunately, I couldn't reproduce the same in the Codesandbox and I get a ts error. Link to sandbox - link to sandbox

Typescript can't infer the right type for Tablle objects and throws an error

Property 'title' does not exist on type 'ObjectType'

I don't know what I am doing wrong, but seems like I just copied a part of the code from the article and it doesn't work.

import { render } from "react-dom";
import React, { PropsWithChildren } from 'react';


interface Props<ObjectType> {
  objects: ObjectType[];
  properties: {
    key: keyof ObjectType,
    title: string,
  }[];
}

function Table<ObjectType,>(
  { objects, properties }: PropsWithChildren<Props<ObjectType>>,
) {
  return (
    <table>
      <tbody>
        {
          objects.map(object => (
            <div>{object.title}</div>
          ))
        }
      </tbody>
    </table>
  );
}

const PostsPage = () => {
  const posts = [{id: 1, title: 'fsdf'}, {id: 2, title: '222fsdf'}];
  return (
    <div>
      <Table
         objects={posts}
         properties={[
           {
              key: 'title',
              title: 'Title'
            },
         ]}
      />
    </div>
  );
};

const rootElement = document.getElementById("root");
render(<PostsPage />, rootElement);

Upvotes: 0

Views: 103

Answers (1)

HaveSpacesuit
HaveSpacesuit

Reputation: 4014

Usually generics are expressed as <T>, which can be any type. T or (ObjectType) doesn't guarantee anything about what properties it may have. If you try to access a property that TypeScript doesn't know about, it will complain.

If you want to assert that ObjectType has a title property, you can do

type WithTitle = {
  title: string;
};

<ObjectType extends WithTitle>

Or create a one-off object

<ObjectType extends { title: string }>

Though you can use <ObjectType> as your template, I'd recommend sticking with <T>, as it is the common convention, and you won't be tempted to think that T is a defined type, while you may be looking around for the definition of ObjectType.

Upvotes: 3

Related Questions