To prevent the compiler from widening the type of the passed array to string[]
, you will need to utilize const type parameter.
It's important to note that const type parameters are only available in Typescript version 5.0
. In versions prior to that, a possible solution, although a bit cumbersome, is to use const assertion, as demonstrated in @Behemoth's answer.
function convertArrayToObject<const T extends readonly string[]>(keys: T) {}
Once that is in place, the type for the reduce
function needs to be defined. It should be an object where the keys are the elements of the array and the values are regular strings.
To determine the type of elements, indexed access is required:
// 'aa' | 'bb'
type Case1 = ['aa', 'bb'][number]
Adapting this concept to fit our required object:
// type Case2 = {
// aa: string;
// bb: string;
// }
type Case2 = {[K in ['aa', 'bb'][number]]: string}
Looking good so far!
We then need to assert the initial value of the reduce function to this type:
function convertArrayToObject<const T extends readonly string[]>(keys: T) {
return keys.reduce((prev, key) => ({ ...prev, [key]: key }), {} as {[K in T[number]]: string});
}
For testing purposes:
// const result: {
// aa: string;
// bb: string;
// }
const result = convertArrayToObject(['aa', 'bb']);
Try it out in the playground