Home  >  Q&A  >  body text

Infer type based on nearest attribute

I'm hoping someone can help me or clarify if what I'm trying to achieve is possible. I'm currently creating a component and I'm having trouble with type inference. Below is the code.

import { faker } from "@faker-js/faker";
import * as React from "react";

type StringOrNumber = number | string;

type Offset = {
  top?: StringOrNumber;
  left?: StringOrNumber;
  right?: StringOrNumber;
  bottom?: StringOrNumber;
};

type Tab<T extends unknown[]> = {
  label: string;
  items: T;
  render: (item: T[number]) => JSX.Element | null;
  badgeCount?: StringOrNumber;
};

type NotificationProps<T extends Tab<unknown[]>[]> = {
  tabs?: T;
  offset?: Offset;
  heading?: string;
  onMarkAllUsRead?(): void;
};

export default function Notification<T extends Tab<unknown[]>[]>(
  props: NotificationProps<T>,
) {
  return <div>{props.heading}</div>;
}

// Example usage:
<Notification
  offset={{
    top: "50px",
  }}
  tabs={[
    {
      label: "Users",
      items: new Array(5).fill(null).map(() => ({
        name: faker.name.fullName(),
        email: faker.internet.email(),
      })),
      render: (user) => {
        return null;
      },
    },
    {
      label: "Emails",
      items: new Array(5).fill(null).map(() => ({
        type: faker.random.word(),
        body: faker.lorem.paragraph(),
      })),
      render: (email) => {
        return null;
      },
    },
  ]}
/>;

What I want to achieve is to have the parameters in render infer the type of the closest items, but currently its type is unknown. Is there any way to do this? Thanks in advance

P粉118698740P粉118698740233 days ago375

reply all(1)I'll reply

  • P粉798010441

    P粉7980104412024-03-23 00:20:43

    I can't comment because I don't have 50 reputation, but I would say that you will get any errors implicit because you are limiting the generic array to unknown[], which means its items can be Any type. If you did something like this:

    type Tab = {
       label: string;
       items: T;
       render: (item: T[number]) => string | null;
       badgeCount?: string | number;
    };

    Typescript will know that each item in the T array is a number. This is a very simple example, but just so you can point out your error.

    This is my solution.

    reply
    0
  • Cancelreply