Search code examples
arraystypescripttypescript-genericsunion-typesnarrowing

Typescript: How to convert an array of keys into a union type of objects?


1. Array of Strings -> Union of Strings (It works)

I saw a solution creates a union of string literals from an array of strings.

const keys = ["cat", "dog"] as const;

type Keys = typeof keys[number]; // "name" | "age"

2. Array of Strings -> Union of Objects (Is it possible?)

My question is if it's possible to create a union of objects from an array of strings? The code below works, I just want to shorten the SET_PROPERTY_PAYLOAD with something like keyof IObject and generate a union of object types from there.

interface IObject = {
  id: string;
  name: string;
  age: number;
}

// Is it possible to shorten this type using typescript's primitives
type SET_PROPERTY_PAYLOAD = 
| {
    id: string;
    propertyName: "id"; // keyof IObject at index 0
    value: string; // IObject["id"]
  }
| {
    id: string;
    propertyName: "name"; // keyof IObject at index 1
    value: string; // IObject["name"]
  }
| {
    id: string;
    propertyName: "age"; // keyof IObject at index 2
    value: number; // IObject["age"]
  };

My goal for this is to narrow the type of value by inferring from the current value of propertyName.


Solution

  • You want a mapped type.

    interface IObject {
      id: string;
      name: string;
      age: number;
    }
    
    type SET_PROPERTY_PAYLOAD = {
        [K in keyof IObject]: {
            id: string,
            propertyName: K,
            value: IObject[K]
        }
    }[keyof IObject]
    

    This type maps over the keys in IObject and create a new object type for each key.

    SET_PROPERTY_PAYLOAD should then be exactly equivalent to your long form version above.

    See Playground