0

I'd like to be able to convert an array of strings into a dictionary where they strings passed in become the keys of the object (and the value is set to true):

// obj = { foo: true, bar: true );
const obj = toObject("foo", "bar");

This is super simple at runtime with JS but I want the types preserved in TS and this is surprising challenging. Here's an implementation that works at runtime but ends up dumping the object out with a type of all. Yuck.

function toObject<T extends readonly string[]>(...keys: T) {
  return keys.reduce((acc, k) => {
    acc[k] = true;
    return acc;
  }, {} as any);
}

With all we're left with zero value but it's still almost better than not stating as any in the reducer. At least we can index the dictionary at run time. Had we left it alone the type would have been an empty object. Instead what I need is some way to convert an array of strings to union of the strings. Once I have that I can simply type the initial state of the reducer to:

{} as Record<UnionOfStrings, true>;

That said, I can't figure out how to do this conversion.

Anyone know how?

1
  • 1
    const arr = ["foo", "bar"] as const; type Union = typeof arr[number]; Commented Jun 22, 2021 at 21:09

1 Answer 1

1

You don't really need to use .reduce for this, since it's really not much simpler than just using a plain-old for loop. Here's an implementation that I wrote using a for loop, but it can probably be written using .reduce as well, if you wish.

function toObject<T extends readonly string[]>(...keys: T): Record<T[number], true> {
    const obj: Record<string, true> = {};

    for (const key of keys) {
        obj[key] = true;
    }

    return obj;
}

Note the return type: Record<T[number], true>. I think this is what you were looking for.

Sign up to request clarification or add additional context in comments.

1 Comment

ahhh; happy to go with whatever looping structure but that Record<T[number], true> is a gem.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.