Home > OS >  How to set conditional types for object properties
How to set conditional types for object properties

Time:02-08

I have an object with two values. I would like to type check one value conditionally based on the value of its peer. I have looked at various solutions but I cannot get it to work how I would like it to.

I can do something like this (source):

type TypeFruit = "apples" | "bananas";
type TypeMetal = "iron" | "copper";

type InterfaceItem =
  | {
      item: "fruit";
      type: TypeFruit;
    }
  | {
      event: "metal";
      type: TypeMetal;
    };

type ItemTypeParameters = InterfaceItem["type"];

type Item = {
  item: "fruit" | "metal";
  type: ItemTypeParameters;
};

But that produces:

// ✅ Correct
assignItem({
  item: "fruit",
  type: "apples",
});

// ✅ Correct
assignItem({
  item: "fruit",
  type: "copper",
});

What I would like to do is set up the code so that the outcome would be like this:

// ✅ Correct
assignItem({
  item: "fruit",
  type: "apples",
});

// ❌ Wrong
assignItem({
  item: "fruit",
  type: "copper",
});

Is there a way to do this? I've looked at ConditionalTypes, which seems like what I would want, but found them confusing and it seemed like they were for other scenarios like extending types conditionally.

CodePudding user response:

Your original InterfaceItem is already giving you the shape you're looking for - where item: "fruit" is necessarily paired with (and only paired with) a TypeFruit. All you need is that, and nothing else.

type TypeFruit = "apples" | "bananas";
type TypeMetal = "iron" | "copper";
type InterfaceItem =
  | {
      item: "fruit";
      type: TypeFruit;
    }
  | {
      event: "metal";
      type: TypeMetal;
    };

declare const assignItem: (item: InterfaceItem) => null;

assignItem({ // Works
  item: "fruit",
  type: "apples",
});

assignItem({ // Fails
  item: "fruit",
  type: "copper",
});
  •  Tags:  
  • Related