These are chat archives for ramda/ramda

19th
Dec 2018
Miguel Dorta
@ellipticaldoor
Dec 19 2018 11:05
I have the following pipe in typescript
pipe(
  map(prop("a")),
  flatten,
  map(prop("b")),
  uniq,
);
It works as I expect the problem I get is that typescript complains with the following error
error TS2345: Argument of type '<T>(x: ReadonlyArray<T> | ReadonlyArray<T[]> | ReadonlyArray<ReadonlyArray<T>>) => T[]' is not assignable to parameter of type '(x: {}) => {}[]'.
  Types of parameters 'x' and 'x' are incompatible.
    Type '{}' is not assignable to type 'ReadonlyArray<{}> | ReadonlyArray<{}[]> | ReadonlyArray<ReadonlyArray<{}>>'.
      Type '{}' is missing the following properties from type 'ReadonlyArray<ReadonlyArray<{}>>': length, concat, join, slice, and 18 more.
src/services/users/index.ts(6,7): error TS2345: Argument of type '<T>(obj: Record<"b", T>) => T' is not assignable to parameter of type '(x: {}) => {}'.
  Types of parameters 'obj' and 'x' are incompatible.
    Property 'b' is missing in type '{}' but required in type 'Record<"b", {}>'.
I'm doing something wrong?
Einar Norðfjörð
@nordfjord
Dec 19 2018 14:08

You expect the type to be <T>(Val: Array<{a: {b:T}}>) => T[]?

I'm not sure that it can be done in any nice way in typescript. You could cast the result to that type though

Miguel Dorta
@ellipticaldoor
Dec 19 2018 14:09
Im quite new with typescript, How would you cast it @nordfjord ?
Scott Sauyet
@CrossEye
Dec 19 2018 14:13

@ellipticaldoor: Obviously as JS that works fine. Passing [{a: [{b: 1}, {b: 2}, {b: 3}]}, {a: [{b: 42}]}] yields [1, 2, 3, 42], as expected.

It could be simplified by replacing the map(prop(...)) calls with pluck(...) ones, but that minor.

However, I've never really learned to read complicated Typescript types or their error messages.

Miguel Dorta
@ellipticaldoor
Dec 19 2018 14:13
Yes, it's quite hard to read this error
I will try pluck, thanks
Scott Sauyet
@CrossEye
Dec 19 2018 14:14
For instance, this '(x: {}) => {}[]' makes no sense to me. I have no idea what it means. @nordfjord, do you make sense of it?
Miguel Dorta
@ellipticaldoor
Dec 19 2018 14:15
a function that expects and object and returns an array of objects?
Scott Sauyet
@CrossEye
Dec 19 2018 14:15
Do you get that error on the creation of the pipe or on an application of it to some value?
Miguel Dorta
@ellipticaldoor
Dec 19 2018 14:15
the error appears when I try to compile
not on execution
Scott Sauyet
@CrossEye
Dec 19 2018 14:16
Oh, they put the array marker after the type, Java style? I've gotten so used to Hindley-Milner: List Foo is also written [Foo]
Miguel Dorta
@ellipticaldoor
Dec 19 2018 14:17
I think you can use both with typescript
Not 100% sure
Scott Sauyet
@CrossEye
Dec 19 2018 14:19
If you're assigning that expression to a variable, can you annotate it with the type @nordfjord suggested?
Miguel Dorta
@ellipticaldoor
Dec 19 2018 14:22
like this?
const roles: <T>(Val: Array<{a: {b:T}}>) => T[] = pipe(
  map(prop("roles")),
  flatten,
  map(prop("slug")),
  uniq,
);
The error is the same
I tried with pluck and now it looks better
const roles = pipe(
  pluck("roles"),
  flatten,
  pluck("slug"),
  uniq,
);
the error looks simpler
error TS2345: Argument of type '<T>(list: ReadonlyArray<Record<"roles", T>>) => T[]' is not assignable to parameter of type '(x0: {}, x1: {}, x2: {}) => {}[]'.
  Types of parameters 'list' and 'x0' are incompatible.
    Type '{}' is missing the following properties from type 'ReadonlyArray<Record<"roles", {}>>': length, concat, join, slice, and 18 more.
Einar Norðfjörð
@nordfjord
Dec 19 2018 15:16
const roles = pipe(
  pluck("roles"),
  flatten,
  pluck("slug"),
  uniq,
) as any as <T>(val: Array<{a: {b: T | T[]}}>) => T[];
I'd do somehting like this

It's hard to type prop in typescript, on the one hand this works fine:

const prop = <T, K extends keyof T>(prop: K, value: T)=> value[prop];

And gives the correct expectation.

However

const prop = <T, K extends keyof T>(property: K)=> (obj: T)=> obj[property];

Does not work as a type unless you always call it as:

interface User {name: string};

prop<User, 'name'>('name')
Scott Sauyet
@CrossEye
Dec 19 2018 15:22
I think I'm pretty happy with my decision to mostly ignore TypeScript. :smile:
Johnny Hauser
@m59peacemaker
Dec 19 2018 15:42
Is there a functional mutex module around?
I can't think of what a Mutex type should actually be.
Scott Sauyet
@CrossEye
Dec 19 2018 16:30
That's hard to imagine, as FP is all about statelessness, and a mutex is by definition stateful.
Miguel Dorta
@ellipticaldoor
Dec 19 2018 16:53
How can I type id to accept prop as a function?
interface User {
  id: // what to put here?
}

const user: User = {
  id: prop("id")
}
Scott Sauyet
@CrossEye
Dec 19 2018 17:01
With only that information, the type of id is that of a function accepting an object and returning any sort of value, including undefined. I have no idea how that's expressed in TS.
Johnny Hauser
@m59peacemaker
Dec 19 2018 17:05
That might explain my difficulty then :)
Nate Abele
@nateabele
Dec 19 2018 21:20
@ellipticaldoor id: (u: ActualUserType) => WhateverTypeIDIs maybe?