fp-ts icon indicating copy to clipboard operation
fp-ts copied to clipboard

Support for typed key in record.filter

Open richard-ejem opened this issue 3 years ago • 2 comments

🚀 Feature request

Example:

type UserId = '1' | '2' | '3';
declare const users: Record<UserId, User>;
const filteredUsers = pipe(users, record.filter(...));

Current Behavior

Above example produces Record<string, User>

Desired Behavior

Above example produces Record<UserId, User>

Suggested Solution

Add these signatures:

<K extends string, A, B extends A>(refinement: Refinement<A, B>): (fa: Record<K, A>) => Record<K, B>
<K extends string, A>(predicate: Predicate<A>): (fa: Record<K, A>) => Record<K, A>

Who does this impact? Who is this for?

Useful with advanced type usage - limited set of keys, or for example in our case using branded strings for marking entity IDs.

Your environment

Software Version(s)
fp-ts 2.7.0
TypeScript 4.4.3

richard-ejem avatar Nov 15 '21 11:11 richard-ejem

If you are filtering (unlike mapping) you can get less entries, returning Record<UserId, User> is not safe

gcanti avatar Jan 10 '22 08:01 gcanti

If you are filtering (unlike mapping) you can get less entries, returning Record<UserId, User> is not safe

Yep that is technically true, but Typescript is a compromise between usability and correctness (and so is fp-ts - current signature is not safe too). And in this particular case, I still think my suggestion would improve the correctness - Record<string, something> will seem to contain all possible strings, while with my suggestion it will at least limit to previously known keys.

And from pragmatic point of view, I think many people use Record<K, V> where you should theoretically have Partial<Record<K, V>> just to keep things simple, and current implementation would force them to use type assertions which are even more unsafe or implement other workarounds when they need to filter a record.

richard-ejem avatar Jan 10 '22 09:01 richard-ejem