title: Make Component Reusable with Typescript in React
body: <p>Building a React app, I want to make my code as DRY as possible. I started to use Typescript for the first time in this project and I am confronted with the problem of reusability of my components where JSX can be the same for different cases but types and interfaces change. </p>
  
  <p>Here is a real example : The code below is a React component built with TypeScript, Apollo / GraphQL, and Redux. It returns a table of all football teams in my DB, fetched from a backend API. </p>
  
  <p>The thing is, I'd like to use this same component to display a table of games, a table of players, etc. </p>
  
  <p>And I am stuck, for example, with my <code>Team</code> interface. Each team only has an <code>id</code> and a <code>name</code>; but each game has a <code>date</code>, a <code>homeTeam</code> and an <code>awayTeam, a</code>score`, etc. </p>
  
  <p>Hence how can I manage my interfaces and my types so that I can reuse this component ? </p>
  
  <pre><code>import React from 'react';
  import { connect } from 'react-redux';
  import { setView, toggleDeleteElemModal } from '../../redux/actions';
  
  import gql from 'graphql-tag';
  import { Query } from 'react-apollo';
  import { ApolloError } from 'apollo-client';
  
  import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
  import { faInfo, faEdit, faTrash } from '@fortawesome/free-solid-svg-icons';
  
  interface SectionTableProps {
    setView: typeof setView
    toggleDeleteElemModal : typeof toggleDeleteElemModal
  }
  
  interface Team {
    id: string;
    name: string;
  }
  
  interface Data {
    allTeams?: Team[];
  }
  
  interface SectionTableQueryProps {
      allTeams: Team[];
      error?: ApolloError;
      loading: boolean;
  }
  
  const GET_ALL_TEAMS = gql`
    query {
      allTeams {
        id
        name
      }
    }
  `;
  
  class SectionTableQuery extends Query&lt;Data, {}&gt; {}
  
  const SectionTable = (props: SectionTableProps) =&gt; (
    &lt;table className="table table-hover table-responsive"&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th scope="col"&gt;ID&lt;/th&gt;
          &lt;th scope="col"&gt;Name&lt;/th&gt;
          &lt;th scope="col"&gt;Actions&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
        &lt;SectionTableQuery query={GET_ALL_TEAMS}&gt;
        {({ data: { allTeams = [] } = {}, error, loading }) =&gt; {
          if (loading) {
            return &lt;tbody&gt;&lt;tr&gt;&lt;td&gt;LOADING&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;
          };
          if (error !== undefined) {
            return &lt;tbody&gt;&lt;tr&gt;&lt;td&gt;ERROR&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;
          };
          return (
            &lt;tbody&gt;
              {allTeams.map((team: Team) =&gt; (
                  &lt;tr key={team.id}&gt;
                    &lt;th scope="row"&gt;{team.id}&lt;/th&gt;
                    &lt;td&gt;{team.name}&lt;/td&gt;
                    &lt;td className="d-flex justify-content-between"&gt;
                    &lt;div onClick={() =&gt; props.setView("info")}&gt;
                      &lt;FontAwesomeIcon icon={faInfo} /&gt;
                    &lt;/div&gt;
                    &lt;div onClick={() =&gt; props.setView("edit")}&gt;
                      &lt;FontAwesomeIcon icon={faEdit} /&gt;
                    &lt;/div&gt;
                    &lt;div onClick={() =&gt; props.toggleDeleteElemModal()}&gt;
                      &lt;FontAwesomeIcon icon={faTrash} /&gt;
                    &lt;/div&gt;
                    &lt;/td&gt;
                  &lt;/tr&gt;
  
              ))}
            &lt;/tbody&gt;
          );
        }}
      &lt;/SectionTableQuery&gt;
    &lt;/table&gt;
  )
  
  const mapDispatchToProps = { setView, toggleDeleteElemModal }
  
  export default connect(null, mapDispatchToProps)(SectionTable);
  </code></pre>