-
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
Add Array.prototype.groupBy[toMap] to JS lib definitions. #47171
Comments
Open for someone to take a look. I'm not quite sure off the bat what this should look like FWIW. I think we probably need to make the same assumptions as we do with |
I asked, and we generally think this might be ok to have the more accurate typing accurately reflecting the source object. Will need a bit of testing out when there's a PR |
Yeah, I think we could think of this as closer to |
I feel like there is something close you can get with reversed mapped types - we discussed this in a recent design meeting about correlated unions. #47109 for some description of this. |
@orta @DanielRosenwasser Can you assign this to me? |
We don't assign issues to external folks, you're welcome to make the PR as long as there isn't an existing one (which you would see in this issue's timeline above) - so go for it |
@orta Thanks. Its my first time to contribute to TypeScript. So can you give me some tips and how to get started on this issue? |
@DanielRosenwasser I want to work on this issue. It's my first time to contribute to Typescript. Is it possible for you to give me some information? |
You mean there would be a problem with the following overload, or have I misunderstood? interface ObjectConstructor {
fromEntries<K extends PropertyKey, T = any>(entries: Iterable<readonly [K, T]>): Record<K, T>;
} |
Well, I don't know if you can have multiple overloads, but that fails in the case of heterogenous property types: interface ObjectConstructor {
fromEntries<K extends PropertyKey, T = any>(entries: Iterable<readonly [K, T]>): Record<K, T>;
}
Object.fromEntries([["a", 42], ["b", "hello"]]); // errors @niieani has a PR at #50203 but it fails once the value is not interface ObjectConstructor {
fromEntries<KeyValue extends readonly [PropertyKey, any]>(
entries: Iterable<KeyValue>,
): [KeyValue] extends [[PropertyKey, any]]
? { [k: string]: KeyValue[1] }
: { [K in KeyValue[0]]: KeyValue extends readonly [K, infer V] ? V : never };
}
const a = [["a", 42], ["b", "hello"]];
Object.fromEntries(a)
// ~ error (CC @sandersn) |
Oh, back on-topic, it looks like there were web-compatibility problems with the name Array.prototype.groupBy (issue: tc39/proposal-array-grouping#37) and with the next name they tried, Array.prototype.group (issue: tc39/proposal-array-grouping#44). It looks like people are now thinking that the next thing to try is adding groupBy/groupToMap functionality as static factory methods on Object and Map, (PR tc39/proposal-array-grouping#47), with no particular provision for subclasses. We didn't need provision for subclasses anyway …which makes sense to me because:
Anyway, the functions on Array.prototype didn't make any specific provision for subclasses, either. |
@DanielRosenwasser Just FYI, I've addressed these failure cases, though the overall complexity has increased. The strict and sound typing for Object.fromEntries is published in an NPM package |
The proposal has moved Here are the type declarations I'm using for reference (though I'm not sure about the soundness issue): global {
interface ObjectConstructor {
groupBy<T>(
items: Iterable<T>,
callbackfn: (value: T, index: number) => string,
): Record<string, T[]>;
}
interface MapConstructor {
groupBy<T, U>(
items: Iterable<T>,
callbackfn: (value: T, index: number) => U,
): Map<U, T[]>;
}
} If you're committing them here or to another open source project, please attribute me. For example, using git:
|
@nickmccurdy thanks for this! Some small improvements that I needed to make:
declare global {
interface ObjectConstructor {
groupBy<Item, Key extends PropertyKey>(
items: Iterable<Item>,
keySelector: (item: Item, index: number) => Key,
): Record<Key, Item[]>;
}
interface MapConstructor {
groupBy<Item, Key>(
items: Iterable<Item>,
keySelector: (item: Item, index: number) => Key,
): Map<Key, Item[]>;
}
} |
Drive-by: the type for the Object version should be at least a little more precise. E.g. declare function
ObjectGroupBy<Item, K extends PropertyKey>(
items: Iterable<Item>,
keySelector: (item: Item, index: number) => K,
): Record<K, Item[]>; so that if your selector returns (e.g.) one of a fixed list of string values, that is reflected in the type of the result (like this). |
Thanks for the generic parameter idea @bakkot, updated my post above with credit to you 🙌 |
|
+1 and its now a static on Map |
bump +1 |
|
I stumbled upon that: Returning Using |
I’d like to +1 @nikeee there, I raised DefinitelyTyped/DefinitelyTyped#67896 yesterday but we agreed it might be an issue for TypeScript core to determine, since it revolves around the utility of I’ll argue that a very common (or at least very useful) use of Object.groupBy([2, 4, 6], value => value % 2 === 0 ? "even" : "odd"); I think it is reasonable that some number of these filter-like use-cases will pass an array that may not satisfy all branches of the comparator. In all of these cases, the outputs will be incorrectly typed. The example above will produce I can understand if it doesn’t make sense to change the output type to (Additionally, the lift of |
Well, if the passend array is empty, the result will be an empty object, so the type would be completely wrong if we're not returning a Partial. I think this isn't even an edge case and it will happen very often. In fact, I ran into this issue when I used a polyfill. |
And since Daniel is already comparing this to
const arr: Array<["A", 1] | ["B", 2]> = [];
let o = fromEntries(arr);
let m: number = o.A; |
Typing as |
Went ahead and opened #56805. I credited @nickmccurdy in the commit per request above; if anyone else who contributed wants to be credited as well I'm happy to add you. |
The proposal for
Array.prototype.groupBy
andArray.prototype.groupByToMap
reached stage 3 recently.Search terms: proposal-array-grouping array groupBy ernest
lib Update Request
With advancement into stage 3, it's time for JS engines, transpilers and toolings to start implementing support for new features and provide feedback for the proposal's advancement into stage 4.
Configuration Check
This is so new that it needs to go into
ESNext
target.Missing / Incorrect Definition
Missing
Array.prototype.groupBy
andArray.prototype.groupByToMap
.Sample Code
Sample code from https://github.com/es-shims/Array.prototype.groupBy
Documentation Link
Proposal: proposal-array-grouping
Shim implementation that can the code can be tested against: es-shims/Array.prototype.groupBy
The text was updated successfully, but these errors were encountered: