Home > Mobile >  Generate type out of multiple objects in array
Generate type out of multiple objects in array

Time:04-12

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

CodePudding user response:

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

  • Related