Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions test/filter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,8 @@ expectType<(number | undefined)[]>(filter(x => x != null, [] as (number | undefi
// filter(() => narrow, dist)
// no need for type annotations when using full signature
expectType<Record<string, string>>(filter(isNotNil, {} as Dict));


// filter(() => narrow)(dist)
expectType<Map<string, string>>(filter(isNotNil, new Map<string, string | undefined>()));
expectType<Map<string, number>>(filter(gt5, new Map<string, number>()));
Comment on lines +95 to +97
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First, these tests are for // filter(() => narrow, map)

Second, you need to be far more exhaustive with your test additions. This file has test coverage for all curry varieties and argument type overloads. You added support for a new argument type, so you need to add tests for each curry call variation

12 changes: 10 additions & 2 deletions types/filter.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,18 @@ export function filter<A, P extends A>(
<B extends A>(list: readonly B[]): P[];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Github doesn't let you add suggests to unchanged code, but you need to add type support for Map here too. This whole things should be:

// filter(() => narrow)
export function filter<A, P extends A>(
  pred: (val: A) => val is P,
): {
  // filter(() => narrow)(map)
  <K, B extends A>(map: Map<K, B>): Map<K, P>;
  // if we put `Record<string, A>` first, it will actually pic`A[]` as well
  // so it needs to go first
  // filter(() => narrow)(list)
  <B extends A>(list: readonly B[]): P[];
  // filter(() => narrow)(dict)
  <B extends A>(dict: Record<string, B>): Record<string, P>;
  // but we also want `A[]` to be the default when doing `pipe(filter(fn))`, so it also needs to be last
  // filter(() => narrow)(list | dict)
  <B extends A>(list: readonly B[]): P[];
};

};

// filter(() => boolean)
// filter(() => boolean)(list | dict)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// filter(() => boolean)(list | dict)
// filter(() => boolean)

export function filter<T>(
pred: (value: T) => boolean,
): <P extends T, C extends readonly P[] | Record<string, P>>(collection: C) => C;
): {
<K>(map: Map<K, T>): Map<K, T>;
<P extends T, C extends readonly P[] | Record<string, P>>(collection: C): C;
Comment on lines +17 to +18
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<K>(map: Map<K, T>): Map<K, T>;
<P extends T, C extends readonly P[] | Record<string, P>>(collection: C): C;
// filter(() => boolean)(map)
<K>(map: Map<K, T>): Map<K, T>;
// filter(() => boolean)(list | dict)
<P extends T, C extends readonly P[] | Record<string, P>>(collection: C): C;

};

// filter(() => narrow, map)
export function filter<K, T, P extends T>(pred: (val: T) => val is P, map: Map<K, T>): Map<K, P>;
// filter(() => boolean, map)
export function filter<K, T>(pred: (val: T) => boolean, map: Map<K, T>): Map<K, T>;

// filter(() => narrow, list) - readonly T[] falls into Record<string T> for some reason, so list needs to come first
export function filter<T, P extends T>(pred: (val: T) => val is P, list: readonly T[]): P[];
Expand Down
Loading