-
Notifications
You must be signed in to change notification settings - Fork 22
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(partition): stricter types, add test #89
Conversation
<L extends T = T>(list: readonly L[]): [(L & U)[], Exclude<L, U>[]]; | ||
(list: readonly T[]): [(T & U)[], Exclude<T, U>[]]; | ||
}; | ||
export function partition<T>(fn: (a: T) => boolean): <L extends T = T>(list: readonly L[]) => [L[], L[]]; |
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.
The fn: (a: T) => a is U
support is a great addition.
Thank you for removing the string
specific overload as well. That was copy/pasted from the original definition over in @types/ramda
. I'm not sure why it was needed as the generic overload covers that case as well
Couple things:
The order of the overloads is important, you need to have partition(fn)(list)
defined before partition(fn, list)
. When passing partition
to another function, eg flip(partition)
, typescript asumes the last overload as the most general and uses that
export function partition<T, U extends T>(fn: (a: T) => a is U): {
<L extends T = T>(list: readonly L[]): [(L & U)[], Exclude<L, U>[]];
(list: readonly T[]): [(T & U)[], Exclude<T, U>[]];
};
I don't understand the 2 overloads in the middle
<L extends T = T>(list: readonly L[]): [(L & U)[], Exclude<L, U>[]];
- What is the generic
L
accomplishing here?
- What is the generic
(list: readonly T[]): [(T & U)[], Exclude<T, U>[]];
- The intersection
T & U
seems extranious.U
is already defied to extendT
, and therefore is a subset ofT
. So by definitionT & U === T
.
- The intersection
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.
- the first overload is required for this test:
Line 12 in 8e6cae9
expectType<[true[], false[]]>(partition((v): v is true => !!v)([true, false])); Lines 15 to 17 in 8e6cae9
const isBool = (v: any): v is boolean => typeof v === 'boolean'; const extractBool = partition(isBool); expectType<[boolean[], number[]]>(extractBool([1, true])); - I removed the useless intersection
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.
Ah ok, the <L extends T= T>
generic makes sense to me now, here is an example that uses an isNumber
function: https://tsplay.dev/mpz56w
We actually don't need both of these then:
<L extends T = T>(list: readonly L[]): [(L & U)[], Exclude<L, U>[]];
(list: readonly T[]): [(T & U)[], Exclude<T, U>[]];
Just have it be
<L extends T = T>(list: readonly L[]): [(L & U)[], Exclude<L, U>[]];
I'm glad to know about this trick, there should be many other places where we can apply it
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.
Turns out that's how filter
works, so at least we're consistent now!
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.
FYI, types of rxjs, which have a great implementation of a pipe
pattern, are almost all functions retuning generic functions just like this
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.
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.
For pipe, yes, but I was thinking about operators
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.
Which operators?
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.
Sorry one last thing, the overloads, both (fn)(arr)
s need to be before (fn, arr)
so this:
partition(fn: val is T)(arr)
partition(fn: boolean)(arr)
partition(fn: val is T, arr)
partition(fn: boolean, arr)
The rule is "specific first, general last", and while it doesn't exactly explain it here: https://www.typescriptlang.org/docs/handbook/declaration-files/do-s-and-don-ts.html#function-overloads, that does include for currying
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.
While testing this, I discovered a very interesting edge case for For |
What do you need from me to consider this PR as mergeable ? |
@GerkinDev I merged #90, so
|
<L extends T = T>(list: readonly L[]): [(L & U)[], Exclude<L, U>[]]; | ||
(list: readonly T[]): [(T & U)[], Exclude<T, U>[]]; | ||
}; | ||
export function partition<T>(fn: (a: T) => boolean): <L extends T = T>(list: readonly L[]) => [L[], L[]]; |
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.
Sorry one last thing, the overloads, both (fn)(arr)
s need to be before (fn, arr)
so this:
partition(fn: val is T)(arr)
partition(fn: boolean)(arr)
partition(fn: val is T, arr)
partition(fn: boolean, arr)
The rule is "specific first, general last", and while it doesn't exactly explain it here: https://www.typescriptlang.org/docs/handbook/declaration-files/do-s-and-don-ts.html#function-overloads, that does include for currying
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.
Looks good
No description provided.