From 7436e44b2486b5455403d353e160fd839f27f774 Mon Sep 17 00:00:00 2001 From: Tim Seckinger Date: Wed, 14 Jun 2023 12:20:23 +0200 Subject: [PATCH 1/4] fix(groupBy): return Partial Record The grouping classifier function may have never returned one of the possible values, so there is not necessarily an array for each group. Note: The test is sort of copied from DefinitelyTyped. I noticed you seem to use `tsd expect*` functions in the other test, but wanted to avoid putting a huge `expectType` of sorts. Testing this way seems like a pretty good idea here, because it's user-focused ('this expression with the groupBy result is allowed, this one is not'). Feel free to amend the test if you don't like that part. --- test/groupBy.test.ts | 16 ++++++++++++++++ types/groupBy.d.ts | 4 ++-- 2 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 test/groupBy.test.ts diff --git a/test/groupBy.test.ts b/test/groupBy.test.ts new file mode 100644 index 0000000..15cac78 --- /dev/null +++ b/test/groupBy.test.ts @@ -0,0 +1,16 @@ +import { groupBy } from '../es'; + +const byGrade = groupBy((student: { score: number; name: string }) => { + const score = student.score; + return score < 65 ? 'F' : score < 70 ? 'D' : score < 80 ? 'C' : score < 90 ? 'B' : 'A'; +}); +const students = [ + { name: 'Abby', score: 84 }, + { name: 'Eddy', score: 58 }, + { name: 'Jack', score: 69 } +]; + +const grouped = byGrade(students); +(grouped.C ?? []).length; +// @ts-expect-error +grouped.C.length; diff --git a/types/groupBy.d.ts b/types/groupBy.d.ts index 07ad83b..0bbcaf5 100644 --- a/types/groupBy.d.ts +++ b/types/groupBy.d.ts @@ -1,2 +1,2 @@ -export function groupBy(fn: (a: T) => K, list: readonly T[]): Record; -export function groupBy(fn: (a: T) => K): (list: readonly T[]) => Record; +export function groupBy(fn: (a: T) => K, list: readonly T[]): Partial>; +export function groupBy(fn: (a: T) => K): (list: readonly T[]) => Partial>; From b1522ded40e9d26dec392feacbe716f61aa36148 Mon Sep 17 00:00:00 2001 From: Tim Seckinger Date: Fri, 23 Jun 2023 10:04:50 +0200 Subject: [PATCH 2/4] switch the overload order and add support for __: Placeholder Co-authored-by: Harris Miller --- types/groupBy.d.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/types/groupBy.d.ts b/types/groupBy.d.ts index 0bbcaf5..0c9b567 100644 --- a/types/groupBy.d.ts +++ b/types/groupBy.d.ts @@ -1,2 +1,5 @@ -export function groupBy(fn: (a: T) => K, list: readonly T[]): Partial>; +import { Placeholder } from './util/tools'; + export function groupBy(fn: (a: T) => K): (list: readonly T[]) => Partial>; +export function groupBy(__: Placeholder, list: readonly T[]): (fn: (a: T) => K) => Partial>; +export function groupBy(fn: (a: T) => K, list: readonly T[]): Partial>; From b8b57134af7fdb70a49bc5d25d9146cae6e3dbe9 Mon Sep 17 00:00:00 2001 From: Tim Seckinger Date: Fri, 23 Jun 2023 10:16:26 +0200 Subject: [PATCH 3/4] placeholder test case --- test/groupBy.test.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/test/groupBy.test.ts b/test/groupBy.test.ts index 15cac78..49bfc77 100644 --- a/test/groupBy.test.ts +++ b/test/groupBy.test.ts @@ -1,4 +1,6 @@ -import { groupBy } from '../es'; +import { groupBy, __ } from '../es'; + +// returns optional arrays for the groups const byGrade = groupBy((student: { score: number; name: string }) => { const score = student.score; @@ -14,3 +16,11 @@ const grouped = byGrade(students); (grouped.C ?? []).length; // @ts-expect-error grouped.C.length; + +// accepts a placeholder and later specifying the grouping function + +const byGrade2 = groupBy(__, students); +byGrade2((student: { score: number; name: string }) => { + const score = student.score; + return score < 65 ? 'F' : score < 70 ? 'D' : score < 80 ? 'C' : score < 90 ? 'B' : 'A'; +}); From 46bf279b7991ba6a47ce82122a20c97352682c62 Mon Sep 17 00:00:00 2001 From: Tim Seckinger Date: Wed, 28 Jun 2023 15:45:23 +0200 Subject: [PATCH 4/4] add some tsd --- test/groupBy.test.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/groupBy.test.ts b/test/groupBy.test.ts index 49bfc77..64408cd 100644 --- a/test/groupBy.test.ts +++ b/test/groupBy.test.ts @@ -1,3 +1,4 @@ +import { expectType } from 'tsd'; import { groupBy, __ } from '../es'; // returns optional arrays for the groups @@ -13,6 +14,7 @@ const students = [ ]; const grouped = byGrade(students); +expectType<{ score: number; name: string }[] | undefined>(grouped.C); (grouped.C ?? []).length; // @ts-expect-error grouped.C.length; @@ -20,7 +22,8 @@ grouped.C.length; // accepts a placeholder and later specifying the grouping function const byGrade2 = groupBy(__, students); -byGrade2((student: { score: number; name: string }) => { +const grouped2 = byGrade2((student: { score: number; name: string }) => { const score = student.score; return score < 65 ? 'F' : score < 70 ? 'D' : score < 80 ? 'C' : score < 90 ? 'B' : 'A'; }); +expectType<{ score: number; name: string }[] | undefined>(grouped2.C);