Skip to content
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

Typescript applies wrong definition for pipe(map) composition. #411

Closed
gokaykucuk opened this issue Apr 2, 2020 · 3 comments
Closed

Typescript applies wrong definition for pipe(map) composition. #411

gokaykucuk opened this issue Apr 2, 2020 · 3 comments

Comments

@gokaykucuk
Copy link

I am relatively new to functional programming and typescript, so please check if what i am doing makes sense first.

If i write a simple pipe as following,

export const faunaIndexDef = pipe(
	map((columnName: string) => ({ field: ["data", columnName] })),
	concat([{ field: ["ref"] }])
);

Typescript compiler as follows,

    Argument of type '(x: Dictionary<string>) => Dictionary<{ field: string[]; }>' is not assignable to parameter of type '(x0: Dictionary<string>, x1: unknown, x2: unknown) => readonly { field: string[]; }[]'.
      Type 'Dictionary<{ field: string[]; }>' is missing the following properties from type 'readonly { field: string[]; }[]': length, concat, join, slice, and 16 more.       

14  map((columnName: string) => ({ field: ["data", columnName] })),
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  node_modules/rambda/index.d.ts:505:17
    505 export function pipe<V0, V1, V2, T1, T2>(fn0: (x0: V0, x1: V1, x2: V2) => T1, fn1: (x: T1) => T2): (x0: V0, x1: V1, x2: V2) => T2;
                        ~~~~
    The last overload is declared here.

For some reason typescript compiler gets the map the definition at index.d.ts:393, which has the signature, export function map<T, U, S>(mapFn: MapFunctionObject<T, U>): (x: Dictionary<T>) => Dictionary<U>;, even if what i am trying to do is not including any Dictionaries.

If I move this definition to line 395, then typescript compiler doesn't throw any errors.
The original file:

export function map<T, U>(mapFn: MapFunctionObject<T, U>, x: Dictionary<T>): Dictionary<U>;
export function map<T, U, S>(mapFn: MapFunctionObject<T, U>): (x: Dictionary<T>) => Dictionary<U>;
export function map<T, U>(mapFn: MapFunctionArray<T, U>, x: T[]): U[];
export function map<T, U>(mapFn: MapFunctionArray<T, U>): (x: T[]) => U[];
export function map<T>(mapFn: MapFunctionArray<T, T>): (x: T[]) => T[];
export function map<T>(mapFn: MapFunctionArray<T, T>, x: ReadonlyArray<T>): T[];

Updated version:

export function map<T, U>(mapFn: MapFunctionObject<T, U>, x: Dictionary<T>): Dictionary<U>;
export function map<T, U>(mapFn: MapFunctionArray<T, U>, x: T[]): U[];
export function map<T, U>(mapFn: MapFunctionArray<T, U>): (x: T[]) => U[];
export function map<T, U, S>(mapFn: MapFunctionObject<T, U>): (x: Dictionary<T>) => Dictionary<U>;
export function map<T>(mapFn: MapFunctionArray<T, T>): (x: T[]) => T[];
export function map<T>(mapFn: MapFunctionArray<T, T>, x: ReadonlyArray<T>): T[];

I am not sure what is the root cause, but my wild guess is something related to number of arguments functions take makes typescript compiler give them priority or it's just wrong.

I am also not exactly sure if this is a typescript-library problem or it's caused by how I am trying to use it.

@selfrefactor
Copy link
Owner

selfrefactor commented Apr 4, 2020

Screenshot_20200404_145526

The error is the same as yours.

I will investigate further, I just wanted to share what happens if I use Ramda typings. For most of the typings I try to follow Ramda typings, but in this case you can see that Ramda typings inself doesn't work well with pipe. Those typings made me stop using compose and pipe with Typescript - currently they don't work well together.

@gokaykucuk
Copy link
Author

I will investigate further, I just wanted to share what happens if I use Ramda typings. For most of the typings I try to follow Ramda typings, but in this case you can see that Ramda typings inself doesn't work well with pipe. Those typings made me stop using compose and pipe with Typescript - currently they don't work well together.

The main reason I've switched to Rambda was to use in-house developed types. As far as I know Ramda types are supplied by others than the main devs and they are quite inconsistent. I had many issues with those as you did. Thanks for looking into the problem 👍

selfrefactor added a commit that referenced this issue Apr 6, 2020
@selfrefactor
Copy link
Owner

selfrefactor commented Apr 6, 2020

I just checked your suggestion - to change order of lines. Typings tests didn't broke so I will go and release it with the next bump.

I am keeping the issue open, as I have to assure that this change is moved to the other branch I am working on.

In regards to Ramda typings - the developers who wrote them, definitely know Typescript more than me. The main reason for the quality is one still unresolved Typescript issue. which forces such style for methods such as R.compose/pipe

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants