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

R.converge bad signature in @types/ramda #118

Open
adellamaggiora opened this issue May 27, 2022 · 9 comments
Open

R.converge bad signature in @types/ramda #118

adellamaggiora opened this issue May 27, 2022 · 9 comments

Comments

@adellamaggiora
Copy link

the following function declaration generates a typescript compile error:

const userMatchRoles = user => roles => R.converge(R.or, [R.includes(user.role), R.isEmpty])(roles);

of course the error is not raised due to typescript strict mode (set to false) but from a bad signature in @types/ramda

@CrossEye
Copy link
Member

@adellamaggiora: We have people now looking into bringing the TS typings in-house. It's not clear how long that will take, but in the meantime, you might want to bring it up with the DefinitelyTyped folks.

Just out of curiosity, is there any real reason for the inner lambda? It looks like this would do the same job and be simpler:

const userMatchRoles = user => R.converge(R.or, [R.includes(user.role), R.isEmpty])

I would also replace converge with lift whenever I can (which isn't always!) So this looks better still to me:

const userMatchRoles = user => R.lift(R.or)(R.includes(user.role), R.isEmpty)

@adispring
Copy link
Member

@adellamaggiora Because all functions of ramda are auto curried, they do not work well together with ts.

By now, one solution for ramda user is that: if a ramda api used as an argument of other functions, people should always explicitly write all the parameters and types to help ts compiler infer the right type, as follows:

const userMatchRoles = (user: { role: string }) => (roles: string[]) =>
    R.converge((a: boolean, b: boolean) => R.or(a, b), [R.includes(user.role), R.isEmpty])(roles);

@valerii15298 Can you look at this issue in spare time?

@valerii15298
Copy link

The signature for converge in @types/ramda is intended to work like that. Typescript cannot infer which arity of R.or to use and is using arity of 1 automatically. The description of how to solve it, is explained in tests here

@adispring solution seems most accurate to me.

Sometimes you need more control and second option to use is this:

    const userMatchRoles = (user: any) => (roles: any) =>
        R.converge((...args) => R.or(...args), [R.includes(user.role), R.isEmpty] as const)(roles);

Of course better specify correct types for user and roles arguments instead of any.

@adispring
Copy link
Member

adispring commented May 30, 2022

By now, one solution for ramda user is that: if a ramda api used as an argument of other functions, people should always explicitly write all the parameters and types to help ts compiler infer the right type, as follows:

In order to help people using ramda apis with typescript, I think we should add some guide or tips on how to using ramda apis with typescript more effectively. In the guide, we can list what are the best ways and what should be avoid to do when write ramda with ts.

@adellamaggiora
Copy link
Author

Thanks everybody for the support, I'll follow the advice to make my ts code to work.

It would be nice having a documentation for Ramda ts api too.

@adellamaggiora
Copy link
Author

adellamaggiora commented May 30, 2022

@adellamaggiora: We have people now looking into bringing the TS typings in-house. It's not clear how long that will take, but in the meantime, you might want to bring it up with the DefinitelyTyped folks.

Just out of curiosity, is there any real reason for the inner lambda? It looks like this would do the same job and be simpler:

const userMatchRoles = user => R.converge(R.or, [R.includes(user.role), R.isEmpty])

I would also replace converge with lift whenever I can (which isn't always!) So this looks better still to me:

const userMatchRoles = user => R.lift(R.or)(R.includes(user.role), R.isEmpty)

i'm pretty new using functional paradigm and this is my first real big project using it.
I didn't know operator lift, thanks!

I did without inner lamda too but at the end i put it in my code cause the signature of the function seems more clear (saying what exact parameters it accepts).

@adellamaggiora
Copy link
Author

adellamaggiora commented May 30, 2022

another ts compile error with the following code:

`
const pluckObjectsProps = (data: Object[]) =>
R.pipe(
R.pick,
R.map(R.__, data)
)

const data = [
{ id: 1, name: 'Pippo', age: 100 },
{ id: 2, name: 'Pluto', age: 150 }
];

const plucked = pluckObjectsProps(data)(['name', 'age']);
`

I am having serious difficulties using ramda with typescript and I think it will not be possible for now to use this library with types. I'll try plain javascript without the benefits of vscode linter suggestion 😔.
Thanks anyway for the support.

@adispring
Copy link
Member

This is a good example to show what's the most frequently problems people encounter again and again, when writing ramda with typescript:

When using each ramda api separately with ts, it may works normal most of the time;

But when composing multiple ramda apis with R.compose, R.converge and other high order ramda functions, things are getting worse. Point-free style code make things more worse. Problems occurs here and there, people even can not write a simple function by composing ramda apis. then they are disappoint, and give up finally. They may then use native esnext apis instead.

Ramda is a practical Functional JavaScript library, but not a practical functional typescript library by now.

@CrossEye
Copy link
Member

@adispring: How much of that problem do you imagine we'll be able to fix by bringing the typings in-house? Will it resolve a great deal of it, or are the issues with currying and HKTs too insurmountable for us to be able to significantly reduce this tension?

@kedashoe kedashoe transferred this issue from ramda/ramda Apr 7, 2024
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

4 participants