Home > front end >  Creating a dictionary type from an array type
Creating a dictionary type from an array type

Time:05-31

Say one has a simple object type, X, and a function to create an explicitly-typed array of X, createXList, as follows:

type X = Readonly<{
  a: string
  b: string
}>

type XList = Readonly<X[]>

// TS workaround to create an explicitly-typed X
const createXList = <TXList extends XList>(xList: TXList): TXList => xList
*/

One can then create an explicitly-typed array of X, say xList, like so:

const xList = createXList([
  { a: 'foo', b: 'bar' },
  { a: 'fizz', b: 'buzz' },
] as const)
/*
const xList: readonly [{
    readonly a: "foo";
    readonly b: "bar";
}, {
    readonly a: "fizz";
    readonly b: "buzz";
}]

The question is: How would one create a type for a dictionary where each key is the concatenation of the a and b properties, and the value is simply the value of the array that was used to create each key in the dictionary, while still keeping the explicit typing. For example:

type XListToXDict<T extends XList> = { /* some magic */ }

type Test = XListToXDict<typeof xList>
/*
{
  "foobar": { a: "foo", b: "bar" };
  "fizzbuzz": { a: "fizz", b: "buzz" };
}
*/

So, for example, the type to create a key for a particular X is:

type XToKey<T extends X> = `${T['a']}${T['b']}`

Notes:

One would assume that one could do the following to at least extract the keys for the dictionary (using above XToKey):

type XListToKeys<T extends XList> = XToKey<T[number]>

But this fails due to it instead generating all possible combinations of a and b (in the specific case of xList, that is "foobar" | "foobuzz" | "fizzbar" | "fizzbuzz").

There is then the challenge of selecting a specific item from the array for each value in the dictionary.

Thanks in advance.

CodePudding user response:

You can achieve this using a mapped type and renaming the key names with as.

type XListToXDict<T extends XList> = {
  [K in keyof T & `${bigint}` as T[K] extends { a: infer A, b: infer B } 
    ? `${A & string}${B & string}` 
    : never
  ]: T[K]
}

Playground

  • Related