<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: RobertBrown3</title>
    <description>The latest articles on DEV Community by RobertBrown3 (@robertbrown3).</description>
    <link>https://dev.to/robertbrown3</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1272575%2F58319982-273d-444a-9217-8076dd9e0aed.png</url>
      <title>DEV Community: RobertBrown3</title>
      <link>https://dev.to/robertbrown3</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/robertbrown3"/>
    <language>en</language>
    <item>
      <title>Problems compiling a generic component</title>
      <dc:creator>RobertBrown3</dc:creator>
      <pubDate>Sat, 03 Feb 2024 16:13:36 +0000</pubDate>
      <link>https://dev.to/robertbrown3/problems-compiling-a-generic-component-1l03</link>
      <guid>https://dev.to/robertbrown3/problems-compiling-a-generic-component-1l03</guid>
      <description>&lt;p&gt;I am attempting to implement a table using generics in Typescript. The code I am using is based on a table component provided at:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://www.bekk.christmas/post/2020/22/create-a-generic-table-with-react-and-typescript
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;I am uncertainn if the author of this code tested it before publishing it. Most of it appears to work, but there is a single compilation problem that I am hoping to get some insights on.&lt;/p&gt;

&lt;p&gt;The test data provided is pretty straightforward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    interface Cat {
      name: string;
      age: number;
      gender: string;
      color: string;
      activityLevel?: string; // optional, same as string | undefined
      favoriteFood?: string; // optional, same as string | undefined
    }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The main (Table) component, with props, is below. It is Table.tsx:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    import React from "react";
    import TableHeader from "./TableHeader";
    import TableRows from "./TableRows";

    export type ColumnDefinitionType&amp;lt;T, K extends keyof T&amp;gt; = {
        key: K;
        header: string;
        width?: number;
    }

    export type TableProps&amp;lt;T, K extends keyof T&amp;gt; = {
        data: Array&amp;lt;T&amp;gt;;
        columns: Array&amp;lt;ColumnDefinitionType&amp;lt;T, K&amp;gt;&amp;gt;;
    }

    const style = {
        borderCollapse: 'collapse'
    } as const

    const Table = &amp;lt;T, K extends keyof T&amp;gt;({ data, columns }: TableProps&amp;lt;T, K&amp;gt;): JSX.Element =&amp;gt; {
        return (
            &amp;lt;table style={style}&amp;gt;
                &amp;lt;TableHeader columns={columns} /&amp;gt;
                &amp;lt;TableRows
                    data={data}
                    columns={columns}
                /&amp;gt;
            &amp;lt;/table&amp;gt;
        );
    };

    export default Table;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The component design is pretty straightforward. The Table component has a header and body component.&lt;/p&gt;

&lt;p&gt;The header component, TableHeader.tsx, is below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    import React from "react";
    import {ColumnDefinitionType} from "./Table";

    type TableHeaderProps&amp;lt;T, K extends keyof T&amp;gt; = {
        columns: Array&amp;lt;ColumnDefinitionType&amp;lt;T, K&amp;gt;&amp;gt;;
    }

    const TableHeader = &amp;lt;T, K extends keyof T&amp;gt;({ columns }: TableHeaderProps&amp;lt;T, K&amp;gt;): JSX.Element =&amp;gt; {
        const headers = columns.map((column, index) =&amp;gt; {
            const style = {
                width: column.width ?? 100, // 100 is our default value if width is not defined
                borderBottom: '2px solid black'
            };

            return (
                &amp;lt;th
                    key={`headCell-${index}`}
                    style={style}
                &amp;gt;
                    {column.header}
                &amp;lt;/th&amp;gt;
            );
        });

        return (
            &amp;lt;thead&amp;gt;
            &amp;lt;tr&amp;gt;{headers}&amp;lt;/tr&amp;gt;
            &amp;lt;/thead&amp;gt;
        );
    };

    export default TableHeader;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The body component, called TableRow.tsx, is below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    import React from "react";
    import {ColumnDefinitionType} from "./Table";

    type TableRowsProps&amp;lt;T, K extends keyof T&amp;gt; = {
        data: Array&amp;lt;T&amp;gt;;
        columns: Array&amp;lt;ColumnDefinitionType&amp;lt;T, K&amp;gt;&amp;gt;;
    }

    const style = {
        border: '1px solid black'
    }

    const TableRows = &amp;lt;T, K extends keyof T&amp;gt;({ data, columns }: TableRowsProps&amp;lt;T, K&amp;gt;): JSX.Element =&amp;gt; {
        const rows = data.map((row, index) =&amp;gt; {
            return (
                &amp;lt;tr key={`row-${index}`}&amp;gt;
                    {columns.map((column, index2) =&amp;gt; {
                            return (
                                &amp;lt;td key={`cell-${index2}`} style={style}&amp;gt;
                                    {row[column.key]}
                                &amp;lt;/td&amp;gt;
                            );
                        }
                    )}
                &amp;lt;/tr&amp;gt;
            );
        });

        return (
            &amp;lt;tbody&amp;gt;
            {rows}
            &amp;lt;/tbody&amp;gt;
        );
    };

    export default TableRows;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For completeness, I am including the code for invoking the Table component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    import React from 'react';
    import logo from './logo.svg';
    import './App.css';
    import Table from './Table';

    interface Cat {
      name: string;
      age: number;
      gender: string;
      color: string;
      activityLevel?: string; // optional, same as string | undefined
      favoriteFood?: string; // optional, same as string | undefined
    }

    const data: Cat[] = [
      {
        name: "Mittens",
        color: "black",
        age: 2,
        gender: "female",
        activityLevel: "hight",
        favoriteFood: "milk",
      },
      {
        name: "Mons",
        color: "grey",
        age: 2,
        gender: "male",
        favoriteFood: "old socks",
        activityLevel: "medium",
      },
      {
        name: "Luna",
        color: "black",
        age: 2,
        gender: "female",
        activityLevel: "medium",
        favoriteFood: "fish",
      },
      {
        name: "Bella",
        color: "grey",
        age: 1,
        gender: "female",
        activityLevel: "high",
        favoriteFood: "mice",
      },
      {
        name: "Oliver",
        color: "orange",
        age: 1,
        gender: "male",
        activityLevel: "low",
        favoriteFood: "fish",
      },
    ];

    const columns: ColumnDefinitionType&amp;lt;Cat, keyof Cat&amp;gt;[] = [
      {
        key: 'name',
        header: 'Name',
        width: 150
      },
      {
        key: 'age',
        header: 'Age in years',
      },
      {
        key: 'color',
        header: 'Color'
      }
    ]

    function App() {
      return (
        &amp;lt;div className="App"&amp;gt;
          &amp;lt;Table data={data} columns={columns} /&amp;gt;
        &amp;lt;/div&amp;gt;
      );
    }

    export default App;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When I attempt to compile this code, I am seeing one problem in the TableRow component. I get the following compilation error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    ERROR in src/TableRows.tsx:20:33
    TS2322: Type 'T[K]' is not assignable to type 'ReactNode'.
      Type 'T[keyof T]' is not assignable to type 'ReactNode'.
        Type 'T[string] | T[number] | T[symbol]' is not assignable to type 'ReactNode'.
          Type 'T[string]' is not assignable to type 'ReactNode'.
            Type 'T[string]' is not assignable to type 'ReactPortal'.
              Type 'T[keyof T]' is not assignable to type 'ReactPortal'.
                Type 'T[K]' is not assignable to type 'ReactPortal'.
                  Type 'T[keyof T]' is not assignable to type 'ReactPortal'.
                    Type 'T[string] | T[number] | T[symbol]' is not assignable to type 'ReactPortal'.
                      Type 'T[string]' is not assignable to type 'ReactPortal'.
        18 |                         return (
        19 |                             &amp;lt;td key={`cell-${index2}`} style={style}&amp;gt;
      &amp;gt; 20 |                                 {row[column.key]}
           |                                 ^^^^^^^^^^^^^^^^^
        21 |                             &amp;lt;/td&amp;gt;
        22 |                         );
        23 |                     }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I have looked at documentation for React and Typescript, and I cannot see a reason for that line of code to fail to compile. Perhaps my understanding of string- based indexes is flawed?&lt;/p&gt;

&lt;p&gt;Can someone give some idea of why this line of code is failing, and how I can get this TableRows component to work?&lt;/p&gt;

</description>
      <category>react</category>
      <category>reactgenerics</category>
      <category>typescript</category>
    </item>
  </channel>
</rss>
