Cjmaret
Cjmaret

Reputation: 211

How to use Typescript and Interfaces when passing props down through React components?

I'm passing down a pretty large array of objects through several React components. I was wondering, what is the syntax for writing the types of all the properties in each object (the objects are nested several times)?

I currently have interfaces like below. These are two components, MainContent, which passes props down into Chart:

MainContent component:

interface ComparatorTypes {
  id: string;
  name: string;
}

interface DataTypes {
  jobId: string;
  jobTitle: string;
  descriptionUrl: string;
  totalCompensation: number;
  baseSalary: number;
  longevityPay: number;
  specialPay: number;
  allowances: number;
  paidTimeOff: number;
  holidays: number;
  retirementBenefit: Array<{
    formula: string;
    details: any;
  }>;
  healthBenefit: Array<{
    premium: number;
    details: any;
  }>;
  remoteWork: {
    isAllowed: string;
    details: any;
  };
}

interface QueryTypes {
  agencyName: string;
  id: string;
  data: DataTypes[];
}

interface params {
  comparatorData: ComparatorTypes[];
  queryData: QueryTypes[];
}

export default function MainContent({ comparatorData, queryData }: params) {
  return (
    <S.MainContentComponent>
      <Header />
      <Summary comparatorData={comparatorData} />
      <Chart queryData={queryData} />
    </S.MainContentComponent>
  );
}

and Chart component:


interface ComparatorTypes {
  id: string;
  name: string;
}

interface DataTypes {
  jobId: string;
  jobTitle: string;
  descriptionUrl: string;
  totalCompensation: number;
  baseSalary: number;
  longevityPay: number;
  specialPay: number;
  allowances: number;
  paidTimeOff: number;
  holidays: number;
  retirementBenefit: Array<{
    formula: string;
    details: any;
  }>;
  healthBenefit: Array<{
    premium: number;
    details: any;
  }>;
  remoteWork: {
    isAllowed: string;
    details: any;
  };
}

interface QueryTypes {
  agencyName: string;
  id: string;
  data: DataTypes[];
}

interface params {
  // comparatorData: ComparatorTypes[];
  queryData: QueryTypes[];
}
export default function Chart({ queryData }: params): JSX.Element {
...

You can see how redundant it is to be naming these giant, several-times-nested interfaces before every component that uses this array of objects. Is this normal for Typescript? Is there a better way to do something like this? Or does all this data need to be typed upon being passed down through every component?

Upvotes: 1

Views: 539

Answers (1)

ghybs
ghybs

Reputation: 53185

What forces you to define these identical interfaces explictly for each component?

On the contrary, factorizing them would be the normal choice: that way, they are defined in a single place (single source of truth), and by importing them, you explictly say that you re-use the exact same types.

// Chart.tsx
export interface QueryTypes {
  agencyName: string;
  id: string;
  data: DataTypes[];
}

export interface DataTypes {
  jobId: string;
  jobTitle: string;
  // etc.
}

export default function Chart({
  queryData
}: {
  queryData: QueryTypes[];
}) {}

// Main.tsx
import Chart, { QueryTypes } from ".Chart";
import Summary, { ComparatorTypes } from "./Summary"; // Same for ComparatorTypes

export default function MainContent({
  comparatorData,
  queryData
}: {
  comparatorData: ComparatorTypes[];
  queryData: QueryTypes[];
}) {
  return (
    <S.MainContentComponent>
      <Header />
      <Summary comparatorData={comparatorData} />
      <Chart queryData={queryData} />
    </S.MainContentComponent>
  );
}

Upvotes: 2

Related Questions