Home > Enterprise >  Create a Record from an object of arrays variable in typescript
Create a Record from an object of arrays variable in typescript

Time:10-01

I have a variable that is an object of arrays:

cssColorsObject = {
    red: ["lightsalmon", "salmon", "darksalmon", "lightcoral", "indianred", "crimson", "firebrick", "red", "darkred"],
    orange: ["coral", "tomato", "orangered", "gold", "orange", "darkorange"],
    yellow: [...
}

I would like to create a type/interface for future object variables that contain some of the keys (eg "red", "orange", "yellow"), and some or all of that key color's properties, eg:

{
    red: ["lightsalmon", "salmon"], // OK
    orange: [], //OK
    yellow: ["lightsalmon"], // NOT OK - because light salmon is a color associated with the "red" key in the original object
}

I have worked out the following:

type CssColorKeys = keyof typeof cssColorsObject; // = "red" | "orange" | "yellow" | "green" , etc
type CssColorValues = typeof cssColorsObject[CssColorKeys][number]; // = "lightsalmon" | "salmon"... | "maroon"
type NewRecord = Record<CssColorKeys, CssColorValues> // Not what I want as this requires all properties and the exact same array.

I imagine I need to use partials, but I'm struggling to implement them here.


Full credit to @captain-yossarian for answer below. I just wanted to add a simplified solution, based on his answer:

type CssColorsPartial = Partial<{
    [Prop in keyof typeof cssColorsObject]: Array<typeof cssColorsObject[Prop][number]>;
}>;

CodePudding user response:

First of all, you need to make cssColorsObject immutable.

const cssColorsObject = {
    red: ["lightsalmon", "salmon", "darksalmon", "lightcoral", "indianred", "crimson", "firebrick", "red", "darkred"],
    orange: ["coral", "tomato", "orangered", "gold", "orange", "darkorange"],
    yellow: ['lemon']
} as const

Then iterate through cssColorsObject keys and create the desired type.

type PartialCSS<T extends Record<string, ReadonlyArray<string>>> =
    Partial<{
        [Prop in keyof T]: Array<T[Prop][number]>
    }>

I have used have unpacked T[Prop] array into new similar Array<T[Prop][number]> because T[Prop] is immutable tuple where order of elements is preserved whereas new type does not require exact element order. Drawback, it allows you to use two similar elements.

Whole code:

const cssColorsObject = {
    red: ["lightsalmon", "salmon", "darksalmon", "lightcoral", "indianred", "crimson", "firebrick", "red", "darkred"],
    orange: ["coral", "tomato", "orangered", "gold", "orange", "darkorange"],
    yellow: ['lemon']
} as const


type PartialCSS<T extends Record<string, ReadonlyArray<string>>> =
    Partial<{
        [Prop in keyof T]: Array<T[Prop][number]>
    }>

const result: PartialCSS<typeof cssColorsObject> = {
    red: ['salmon'],
    yellow:['salmon'] // expected error
}

Playground

  • Related