ts-reset icon indicating copy to clipboard operation
ts-reset copied to clipboard

Object.fromEntries

Open Jacob-Lockwood opened this issue 2 years ago • 9 comments

Hey, I'm a fan of your YouTube videos and I'm excited to start using ts-reset in my projects.

One feature I would really appreciate would be better typing for the Object constructor method Object.fromEntries:

// currently:
Object.fromEntries([["a", 5], ["b", 6]] as const) // { [k: string]: "a" | "b" }
// ideally:
Object.fromEntries([["a", 5], ["b", 6]] as const) // { a: 5, b: 6 }

I found an implementation at this blog post:

export type ArrayElement<A> = A extends readonly (infer T)[] ? T : never;
type DeepWriteable<T> = { -readonly [P in keyof T]: DeepWriteable<T[P]> };
type Cast<X, Y> = X extends Y ? X : Y
type FromEntries<T> = T extends [infer Key, any][]
  ? { [K in Cast<Key, string>]: Extract<ArrayElement<T>, [K, any]>[1]}
  : { [key in string]: any }
export type FromEntriesWithReadOnly<T> = FromEntries<DeepWriteable<T>>
function fromEntries<T extends Iterable<readonly [PropertyKey, any]>>(entries: T): FromEntriesWithReadOnly<T> {
  return Object.fromEntries(entries) as any
}

Not my code

Here's a playground link for the implementation: TS Playground Link

I'd be glad to write up a PR if you think this is worth adding.

Jacob-Lockwood avatar Feb 24 '23 17:02 Jacob-Lockwood

Object.entries won't be added - check the readme!

But Object.fromEntries does seem to make sense - could you reduce the scope of this issue and rewrite the description? Or feel free to create a new issue.

mattpocock avatar Feb 24 '23 19:02 mattpocock

@mattpocock Sorry, didn't see that--updated the issue. I can send a PR to add this if you think it would be a good feature

Jacob-Lockwood avatar Feb 24 '23 22:02 Jacob-Lockwood

Let's leave this issue around to see if folks start screaming for it - off the top of my head it feels like a cool feature, but not an essential one.

mattpocock avatar Feb 24 '23 22:02 mattpocock

Hey @mattpocock , I don't want to create another issue. So i gonna post it here since it's related to Object.entities I see your reasoning under not adding Object.entries and from my understanding it's connected to the keys on an object. What about values? TS defines Object.entries(o: {}): [string, any][]; and Object.values(o: {}): any[]; – any is brutal here.

akellbl4 avatar Mar 03 '23 15:03 akellbl4

@akellbl4 Could you create a different issue? As it's unrelated to the current issue.

mattpocock avatar Mar 03 '23 17:03 mattpocock

Moving my example with Object.values and Object.entries inference here since the issue was closed as duplicate

akellbl4 avatar Mar 08 '23 20:03 akellbl4

@akellbl4 My bad! Thanks for your patience.

mattpocock avatar Mar 08 '23 22:03 mattpocock

I was looking for this also, but that example implementation doesn't seem to work for all cases. Given the input type ['a' | 'b', 1], it gives {a: never; b: never}. I don't know if there exists a right thing to do in that case, since the array may or may not contain all items in the union.

I suppose they could all be marked as possibly undefined instead, but I don't know if that's what we'd want either

Briaoeuidhtns avatar Mar 09 '23 23:03 Briaoeuidhtns

I was looking for this also, but that example implementation doesn't seem to work for all cases. Given the input type ['a' | 'b', 1], it gives {a: never; b: never}. I don't know if there exists a right thing to do in that case, since the array may or may not contain all items in the union.

I suppose they could all be marked as possibly undefined instead, but I don't know if that's what we'd want either

I think the right way to deal with this would be { a: 1 } | { b : 1 }, but I have no idea how to implement that

Jacob-Lockwood avatar Jun 07 '23 22:06 Jacob-Lockwood