Skip to content

[0.29.9] pluck inside pipe get ts error #107

Open

Description

@nathan1530

The error msg:

Argument of type '{ <U extends O[keyof O], UK extends keyof U, O extends Record<string, any>>(obj: "value" extends UK ? O : never): { [OK in keyof O]: O[OK]["value"]; }; <U extends readonly unknown[] | Record<"value", any>>(list: readonly U[]): U extends readonly (infer T)[] ? T[] : U extends Record<...> ? T[] : never; }' is not assignable to parameter of type '(...args: Data[][]) => (number | null)[]'.
  Type '{ [x: string]: any; }' is missing the following properties from type '(number | null)[]': length, pop, push, concat, and 25 more.

image

Here is a minimal repo to reproduce the error
https://codesandbox.io/p/devbox/vm2hyt?file=%2Fsrc%2Findex.ts%3A7%2C22

I am not sure if my type in pipe<...> is wrong but it works in 0.29.4

Activity

  1. Harris-Miller commented on Mar 5, 2024

    @Harris-Miller
    Collaborator

    Your R.pipe<> typings is off by a bit: R.pipe<[Data[]], (number | null)[], number[]>(), but that's not the core problem

    The problem here is due a combination of two things. First is the fact that typescript always picks the last overload when you pass a function as a prop. And R.reject has this:

    export function reject<A, P extends A>(
      pred: (val: A) => val is P,
    ): {
      <B extends A>(list: readonly B[]): Array<Exclude<B, P>>;
      <B extends A>(dict: Record<string, B>): Record<string, Exclude<B, P>>;
    };

    R.reject(R.isNil) falls into this and so in your R.pipe, The R.reject is expecting a Record<string, B> and not a B[]. But R.pluck() is now, correctly, returning B[] (#71 fixed that, before it was returning an obj, not an array of objects like it should have, this is why you didn't have the problem before)

    Since most use-cases for R.filter and R.reject is to pass a list and not an object, the list overload should come last. That's how it is on map as well. I actually have an open MR for this: #106. I'm going to add to that MR an update for R.reject as well

    The second is how the new R.pluck is what I have been calling "the collapsing generics problem". You can read about it all here: #54

    The tl;dr is because R.Pluck supports both and object and an array, the generic collapses to unknown, This is specifically due to the fact that there is more than one overload. If you use only one overload, the generic transfers. You can see this in action here: https://tsplay.dev/m3qojw

    A short-term fix for you is to not use the curried varieties of those functions, and wrap them with arrow functions in your pipe

    const extract = R.pipe<[Data[]], (number | null)[], number[]>(
      x => R.pluck("value", x),
      x => R.reject(R.isNil, x),
    );

    This is far from ideal, but will get around the typing problem until we can release a fix

  2. nathan1530 commented on Mar 6, 2024

    @nathan1530
    Author

    Thank you for responding so quickly. I will use the workaround for now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions