-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat request: allow preserving keys (+ types by key) to map over objects #12393
Comments
This is an issue with the declaration files for ramda as they are specified in the linked repo. The new Mapped Types feature #12114 allows this pattern to be expressed very elegantly. |
I hadn't been aware, thank you for pointing this out! :) |
Hi, I think this might be relevant usage of delayed index access type for generic. More info here #11929 (comment). Rambda's API is a perfect usage of that. |
If you'd forgive a follow-up question (which I can take to SO if deemed inappropriate here), I'm trying to figure out how to generalize the
... to enable types separated by key, while in this example we seem to have a single T/U for the whole (multi-key) function call. |
I don't know whether it is possible in the long term. But it is impossible for now. declare function mapObject<T, V, M extends {[k: string]: T}>(func: (v: T) => V, m: M): {[K in keyof M]: V} You can try this for now. It's the best of status quo. |
Thanks! That'll do for now then. :D |
Mapped types should enable these scenarios. The change needed is to update the declaration files. if there are other ones that are not covered please provide more information about why mapped types is not sufficient. |
@mhegazy: I apologize, I'll admit my original example ended up not covering the breadth of my intended result. I've tried to update it accordingly.
.. which HerringtonDarkHolme stated is not presently possible. Note that this becomes relevant in my (updated) example as different keys end up with different value types, dependent on both the transforming function (e.g. |
@ahejlsberg is working on adding inference from mapped types. so you should be able to write something like: declare function map<T, K extends keyof T, U>(fn: (a: T) => U, obj: Record<K, T>): Record<K, U>; |
actually scrap that. it was too late for me last night, and was not thinking right. this is not about generic inference from mapped types. this is about having the function somewhere in the template so that it applies to every property as it is being created. not sure how though.. but i guess we need is somehow apply the function for each value in the template: declare function map<T>(fn: (a: T) => ?, obj: T): { [P in keyof T]: typeof f(T[P]) }; |
Note that a solution here would also extend to allowing
|
Another issue here with the aggressive evaluation of the indexed access type is using another type parameter, for instance, trying to define declare function path<T, K1 extends keyof T, K2 extends keyof T[K1]>(keys: [K1, K2], obj: { [K1]: { [K2]: T } }): T;
`K2` has type `never` here, which is not useful. moreover, there is not way to make this work correctly |
@mhegazy: I tried to see if I could figure out a way to formulate (If you have a good REPL for these things I'd be interested, right now I just tried a In your path example, maybe I can see what went wrong... you stated
If I try this in VSCode, on the K1/K2 (as used in the T definition) it gives me error squiggles If these can be addressed though, I'm hoping to solve the walls of 'definitions for ever-increasing numbers of generics' in my cross-linked reduce proposal. |
I'll track that. Thank you. :) |
@mhegazy: I tried to think this over again, since most other TS issues I have could also be manually addressed by adding type annotations. In your example, I'm a bit unfamiliar with the use of
(Note I referred to the function here using its type, |
There is no way now to expresses the return type of a function. we have an issue #6606 tracking supporting this using |
I'm hoping to be able to properly type functions like Ramda's R.map (for objects) or Lodash's _.mapValues -- in such a way as to acknowledge that mapped over values (which may have been of different types) may give results of different types, dependent on both their respective input type as well as on the mapper function.
Code
Desired behavior:
{ a: number[], b: string[] }
Actual behavior:
{ a: any[], b: any[] }
I apologize for the use of libraries for this example. Probably more verbose without, but the concept is common in FP libraries.
The text was updated successfully, but these errors were encountered: