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
Feature/improve group by key types #143
Feature/improve group by key types #143
Conversation
remeda 0.21.0
update with base
update to 0.0.23
by inferring the type of the key from the provided function; it must still extend a PropertyKey because that's what an object needs as index
@TkDodo Wow, great! I had the same idea after wondering about ): Record<PropertyKey, NonEmptyArray<T> | undefined>; But I'm not sure about this change: microsoft/TypeScript#13195 . It could lead to different semantic. |
@Bessonov why would we need to include |
@TkDodo correct me, if I'm wrong, but without interface MyType {
type: 'right' | 'wrong'
}
const myTypes: MyType[] = [
{ type: 'right' }
]
const grouped = groupBy(myTypes, item => item.type)
grouped.wrong.length <-- fine But it breaks at runtime. |
Or, I think, using
|
@Bessonov you are most certainly right 👍 However, adding
Here, we should be able to access Maybe what I'm trying to do in this PR is not the right thing to do? After all, I think things like this are the reason why TypeScript only returns |
@TkDodo I've created a playground with all three definitions above. It looks like the "Partial"-Definition declare function groupByPartial<Item, Key extends PropertyKey>(
items: readonly Item[], fn: (item: Item) => Key,
): Partial<Record<Key, NonEmptyArray<Item>>> works as expected. What do you think about that?
If I must choose between |
@Bessonov thanks for digging into this. You are right that the I will update the PR to use |
reverse type inference gets even better with this
we can't really access keys directly because they might not exist at runtime, and Partial makes sure of that while still preserving the better key types. this also works well with Object.entries in TS 4.3 and above
@Bessonov have another look please |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great, thanks!
src/groupBy.ts
Outdated
export function indexed<Item, Key extends PropertyKey>( | ||
array: readonly Item[], | ||
fn: PredIndexed<Item, Key> | ||
): Record<Key, NonEmptyArray<Item>>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not using the indexed version, but shouldn't it have same return type?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thx for seeing that, you are right 🙏
const grouped = groupBy(myTypes, item => item.type); | ||
|
||
// @ts-expect-error we can't access keys unconditionally | ||
expect(() => grouped.wrong.length).toThrow(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe add
// @ts-expect-error other values are not allowed by typings
expect(grouped.notexists).toBeUndefined();
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
items: readonly T[], | ||
fn: (item: T) => PropertyKey | ||
): Record<PropertyKey, NonEmptyArray<T>>; | ||
export function groupBy<Item, Key extends PropertyKey>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not related to this PR, but I think we can replace this definition one day:
/** types that may be returned by `keyof` */
export type Key = string | number | symbol;
with PropertyKey
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done: 83e04aa
Great, I'm fine with it, thank you! |
* improve groupBy key typings by inferring the type of the key from the provided function; it must still extend a PropertyKey because that's what an object needs as index * update typescript version reverse type inference gets even better with this * make returnType of groupBy partial we can't really access keys directly because they might not exist at runtime, and Partial makes sure of that while still preserving the better key types. this also works well with Object.entries in TS 4.3 and above * add an extra test for unknown properties * use built-in PropertyKey instead of our own type * fix types for indexed version
This reverts commit 9ea42bc.
by inferring the type of the key from the provided function; it must still extend a PropertyKey because that's what an object needs as index