skip to Main Content

I have a component that fetches data from an API and then displays it in a table. I have a prop that allows a value that is fetched to be displayed differently in the table. This is how I have the prop types right now:

// T is the type of the row, so the data fetched from the API has type T[]
type Props<T extends Record<string, unknown>> = {
  columns: Record<keyof T, ColumnSetting<T>>;
}

type ColumnSetting<T> = {
  header: string;
  customValue?: (value: any, row: T) => React.ReactNode;
}

But I don’t want to use any for the value, I want it to have the correct type. So for example in the example below I want it to infer that the type of value is number (and not string), is this possible?

<CustomTable<{ title: string, percentage: number }>
  columns={{ 
    title: {
      header: 'Title'
    },
    percentage: { 
      header: 'Percentage', 
      customValue: value => value + '%' 
    }
  }}
/>

If tried adding another generic for the key or adding a generic to customValue but I can’t get it to work.

2

Answers


  1. type Props<T extends Record<string, unknown>> = {
      columns: Record<keyof T, ColumnSetting<T>>;
    };
    
    // Define your ColumnSetting type with the correct type for the value parameter
    type ColumnSetting<T> = {
      header: keyof T;
      customValue?: (value: T[keyof T], row: T) => React.ReactNode; // Use T[keyof T] instead of any
    };
    
    // Define your CustomTable component with the generic parameter T
    function CustomTable<T extends Record<string, unknown>>({ columns }: Props<T>) {
      // Your CustomTable implementation here
      return null;
    }
    
    <CustomTable<{ percentage: number }>
      columns={{
        percentage: {
          header: 'percentage',
          customValue: (value) => value + '%',
        },
      }}
    />

    this should do the trick for what you want to do

    Login or Signup to reply.
  2. You just need to use a custom mapped type instead of Record:

    type Props<T extends Record<string, unknown>> = {
      columns: { [P in keyof T]: ColumnSetting<T, T[P]> };
    }
    
    type ColumnSetting<T, V> = {
      header: string;
      customValue?: (value: V, row: T) => React.ReactNode;
    }
    

    Playground Link

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search