Skip to content

Commit

Permalink
Fix: return type of map for when list is object
Browse files Browse the repository at this point in the history
  • Loading branch information
Harris-Miller committed May 26, 2023
1 parent 006d93b commit 650a395
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 4 deletions.
8 changes: 4 additions & 4 deletions types/map.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { FunctorMap, FunctorFantasyLand, Placeholder, ValueOfUnion } from './util/tools';
import { FunctorMap, FunctorFantasyLand, Placeholder, ValueOfUnion, KeysOfUnion } from './util/tools';

// map(fn)
export function map<T, U>(fn: (x: T) => U): {
Expand All @@ -7,7 +7,7 @@ export function map<T, U>(fn: (x: T) => U): {
(list: readonly T[]): U[];
(functor: FunctorFantasyLand<T>): FunctorFantasyLand<U>;
(functor: FunctorMap<T>): FunctorMap<U>;
<O extends Record<PropertyKey, T>>(dict: O): Record<keyof O, U>;
<O extends Record<PropertyKey, T>>(dict: O): Record<KeysOfUnion<O>, U>;
// it also needs to be here when you pass map as an argument to a function, eg `compose(map(fn))`
(list: readonly T[]): U[];
};
Expand All @@ -16,13 +16,13 @@ export function map<T, U>(fn: (x: T) => U): {
export function map<T>(__: Placeholder, list: readonly T[]): <U>(fn: (x: T) => U) => U[];
export function map<A>(__: Placeholder, obj: FunctorFantasyLand<A>): <B>(fn: (a: A) => B) => FunctorFantasyLand<B>;
export function map<A>(__: Placeholder, obj: FunctorMap<A>): <B>(fn: (a: A) => B) => FunctorMap<B>;
export function map<O extends object>(__: Placeholder, dict: O): <U>(fn: (x: ValueOfUnion<O>) => U) => Record<keyof O, U>;
export function map<O extends object>(__: Placeholder, dict: O): <U>(fn: (x: ValueOfUnion<O>) => U) => Record<KeysOfUnion<O>, U>;
// map(fn, list)
// first and last def are the same and are here on purpose
// the list variant needs to come before the FunctorMap ones, because `T[]` is a `FunctorMap<T>`
export function map<T, U>(fn: (x: T) => U, list: readonly T[]): U[];
export function map<T, U>(fn: (x: T) => U, obj: FunctorFantasyLand<T>): FunctorFantasyLand<U>;
export function map<T, U>(fn: (x: T) => U, obj: FunctorMap<T>): FunctorMap<U>;
export function map<O extends object, U>(fn: (x: ValueOfUnion<O>) => U, dict: O): Record<keyof O, U>;
export function map<O extends object, U>(fn: (x: ValueOfUnion<O>) => U, dict: O): Record<KeysOfUnion<O>, U>;
// it also needs to be here when you pass map as an argument to a function, eg `flip(map)`
export function map<T, U>(fn: (x: T) => U, list: readonly T[]): U[];
6 changes: 6 additions & 0 deletions types/util/tools.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,12 @@ export type InputTypesOfFns<A extends ReadonlyArray<Fn>> = A extends [infer H, .
: []
: [];

/**
* When you have a union type, `keyof T` is not sufficient
* <created by @harris-miller>
*/
export type KeysOfUnion<T> = T extends infer U ? keyof U : never;

/**
* If `T` is a union, `T[keyof T]` (cf. `map` and `values` in `index.d.ts`) contains the types of object values that are common across the union (i.e., an intersection).
* Because we want to include the types of all values, including those that occur in some, but not all members of the union, we first define `ValueOfUnion`.
Expand Down

0 comments on commit 650a395

Please sign in to comment.