Abe Caymo
Abe Caymo

Reputation: 311

Infer type of an object property based on object's sibling keys

Consider these array of objects:

  const inputGroup = [
{
    key: "primary_category",
    label: "Primary Category",
    elType: "select",
    elementConfig: {
      options: categories,
    },
  },
  {
    key: "extra_tags",
    label: "Extra tags",,
    elType: "input",
    elementConfig: {
      type: "text",
      placeholder: "e.g. startup, analytics, svelte, seo, social media,",
    },
  },
]

How would I type this so that elementConfig's allowed properties depend on elType's value?

Upvotes: 0

Views: 28

Answers (1)

T.J. Crowder
T.J. Crowder

Reputation: 1074198

You can define a type that has the base properties (key, label) and intersect it with a union of two object types, one with elType: "select" and the relevant type for elementConfig for selects, and another with elType: "text" and the relevant type for elementConfig for text fields, like this:

type GroupEntry =
    {
        key: string;
        label: string;
    } & (
        {
            elType: "select",
            elementConfig: {
                options: string; // Or whatever the type of `categories` should be
            }
        } |
        {
            elType: "input",
            elementConfig: {
                type: string; // Or maybe "text" | "number" | ...
                placeholder?: string;
            }
        }
    )
;

Then you declare your array of that type:

const inputGroup: GroupEntry[] = [
    {
        key: "primary_category",
        label: "Primary Category",
        elType: "select",
        elementConfig: {
            options: "categories",
        },
    },
    {
        key: "extra_tags",
        label: "Extra tags",
        elType: "input",
        elementConfig: {
            type: "text",
            placeholder: "e.g. startup, analytics, svelte, seo, social media,",
        },
    },
    {
        key: "something",
        label: "stuff",
        elType: "select",
        elementConfig: {
            type: "text" // <==== Error as desired
        }
    }
];

Playground link

Upvotes: 1

Related Questions