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]
}