Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

131
Views
How to reduce an array to object while providing auto code completion in typescript?

Lately I'm trying out typescript and while diving into it I was stuck at one place where I wasn't able move forward. So I have an array of strings and I want to reduce it into an object while getting all proper hinting and code completion. Although I've arrived to a place where typescript isn't throwing any error but still I wasn't able to achieve the code completion behaviour. Pasting out the sample code here for reference.

interface GetObjI {
  [key: string]: string;
}

function getObj(myArray: string[]): GetObjI {
  return myArray.reduce((prev, curr) => {
    prev[curr] = curr;
    return prev;
  }, {});
}

const arr = ["name", "age"];

const obj = getObj(arr);

console.log(obj.age); // Here I wasn't able to achieve code completion.
about 4 years ago · Juan Pablo Isaza
1 answers
Answer question

0

With strict TypeScript settings, the code you have should be throwing an error.

prev[curr] = curr;

throws

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{}'.

No index signature with a parameter of type 'string' was found on type '{}'.(7053)

Which makes sense - you aren't providing any special type for the accumulator when you're passing it in, so assigning to a property of it doesn't mesh with its existing type (as an empty object).

Use a generic type argument to indicate the type of the accumulator, and make getObj generic too so that the values in myArray can be passed along (rather than using just string[], which is too general).

You also need to type the array passed in as const so it doesn't get widened to string[] before the function call.

function getObj<T extends readonly string[]>(myArray: T) {
    // Type out the type of the full object with all properties here to be DRY
    type Accum = Record<T[number], T[number]>;
    // The object doesn't have all properties inside the callback, though
    // so we need to use Partial to indicate that some or all can be missing
    return myArray.reduce<Partial<Accum>>((prev, curr: T[number]) => {
        prev[curr] = curr;
        return prev;
    }, {}) as Accum; // When returning, indicate that it's no longer Partial, but has all properties
}

const arr = ["name", "age"] as const;

const obj = getObj(arr);

console.log(obj.age);

But .reduce is not the right tool for this situation - it requires verbose TypeScript typing and is not a great idea even in standard JavaScript because the accumulator remains the same object. Just use a loop.

function getObj<T extends readonly string[]>(myArray: T) {
    const obj: Record<string, string> = {};
    for (const prop of myArray) {
        obj[prop] = prop;
    }
    return obj as Record<T[number], T[number]>;
}

Or use Object.fromEntries

const getObj = <T extends readonly string[]>(myArray: T) =>
    Object.fromEntries(myArray.map(prop => [prop, prop])) as Record<T[number], T[number]>;

Unfortunately, all of these approaches do require helping TS along with some type assertions. Using a loop or reduce requires the properties to be typed as optional inside the loop, but required outside of it - and Object.fromEntries only gives a type of Record<string, T> in response, which isn't quite specific enough.

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!