Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Generate type out of multiple objects in array

I want to make my End-to-End testing easier and typesafer, by collecting and transforming the data-attributes in a typed constant object.
However, I cannot make it work.

How can I create an union type out of an attribute value of multiple objects within an array?

interface Itest {
  name: string
  values: readonly string[]
}

const testAttributes: readonly Itest[] = [
  {
    name: "testid",
    values: [
      "playbarQueueIcon",
      "queueBar",
      "playbarPlayButton",
      "playbarPauseButton",
      "playbarPreviousButton",
      "playbarNextButton",
      // ...
    ] as const,
  } as const,
  {
    name: "testgroup",
    values: ["queueNextTracks", "queuePreviousTracks"] as const,
  } as const,
] as const

// ***********************
// Why does this not work?
// ***********************
type ITest = typeof testAttributes[number]["values"][number]


const attr = testAttributes.reduce((acc, {name, values}) => {
  for (const value of values) {
    acc[value] = `[data-${name}=${value}]`
  }

  return acc
}, {} as Record<ITest, string>
)

attr.queueBarXXXX // => Should not work
attr.queueBar // => Should work

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

Manually setting a type via : readonly Itest[] overrides what could be inferred. So values is string[] because that overrides the as const assertion. Remove that and you get the union I think you expect.

If you want testAttributes to satisfy the Itest[] type but be inferred to something more specific you need to wait for the satisfies operator to land in released typescript: https://github.com/microsoft/TypeScript/issues/47920

Or use a function:

function makeTestArray<T extends Itest[]>(arr: T): T { return arr }
const testAttributes = makeTestArray([...]) // data goes here.

Playground

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading