Typings for Ramda are sometimes non accurate (examples), working with Typescript and Ramda can sometimes be frustrating and somehow badly impact adoption.
This appears to be one of the main pain points in my Ramda lessons.
As this library makes her way to the version 1.0.0 it would be great if we could consider building it in Typescript directly.
@types/ramda or @types/npm-ramda).I'd love to propose a PR! 🥇
If other people share my concern about not writing javascript libraries in javascript, I've come up with a way to solve many of the problems inherent in maintaining type definitions for iter-tools. Typedefs are maintained in the library, and I use a little special sauce to write my tests in such a way that the type checker can verify that typing constraints are not violated. The cool thing is that the approach works even if you intend to have first-class support for both Typescript and flow types, which I do.
@hitmands:
Another well-written proposal.
While I don't have any major objection to including such typings, I do have several concerns.
Chiefly, the current team has little knowledge of, and for the most part I think, little interest in Typescript. So this would mean adding to the team someone who wants to commit to keeping these in sync on every release. Are you interested in doing that?
Should this also include Flow? Would we need a separate person to handle that? What about working with other type systems as they come along? How do we decide when it's become important enough to offer support, or when it's become unimportant enough to drop it? It wasn't that long ago that we'd have been talking about CoffeeScript instead.
I don't know if it's true at the moment, but there have been times when Typescript was not expressive enough to capture certain Ramda functions. If we own the Typescript, do we also have to forgo more sophisticated functions because we cannot express them in Typescript? Or how do we document that certain functions are out-of-bounds in Typescript?
While I agree that it would be worth having control over these typings, I'm simply not sure that the team is ready for the responsibility.
But I would love to see a PR if you're interested in creating one. Perhaps that would show us that it's not as difficult as I imagine.
Chiefly, the current team has little knowledge of, and for the most part I think, little interest in Typescript. So this would mean adding to the team someone who wants to commit to keeping these in sync on every release. Are you interested in doing that?
I'd love to be part of this project, and yes I'd be interested on supporting it. I use ramda every day in every project, I teach ramda and also very active on s.o. ramda topics.
Should this also include Flow? Would we need a separate person to handle that? What about working with other type systems as they come along? How do we decide when it's become important enough to offer support, or when it's become unimportant enough to drop it? It wasn't that long ago that we'd have been talking about CoffeeScript instead.
My proposal is only about Typescript as I think it is the widest used js superset atm. We could easily generate flow definitions via https://github.com/joarwilk/flowgen if the team would also want to support flow.
I don't know if it's true at the moment, but there have been times when Typescript was not expressive enough to capture certain Ramda functions. If we own the Typescript, do we also have to forgo more sophisticated functions because we cannot express them in Typescript? Or how do we document that certain functions are out-of-bounds in Typescript?
Libraries such Ramda are definitely difficult to write in typescript as most of their constructs (e.g. partial application) don't play very nicely with ts. However, as showed by @types/ramda and @types/npm-ramda a lot can be done... It is likely that not everything could be typed safely, and for those cases, we would find a way to properly communicate it. Those are also problems that already exist with current typings... My proposal is about to solve/mitigate them.
And yes, it'd be easier to provide a quick POC of this... It could also help this discussion imho.
I could work on it if you're interested on considering this ts option :)
@CrossEye Are you sure you're on the same page as @hitmands? You talk about having needing to have someone to keep the types in sync. I think the proposal is to actually to change all the js files in the library to ts files. All contributors would then need to know typescript, not just a few to help with libdefs.
@conartist6: you're right, I did misread. I read "we could consider building in Typescript directly," which I took to mean bringing the typings files in-house. What was actually there was "we could consider building it in Typescript directly," which is a very different notion.
@hitmands: We'll have to check with the other contributors, but this is suddenly much less interesting to me. I'm not even slightly interested in writing in TS myself. I suppose there's room for parallel code-bases, but that sounds a bit daunting.
it would be great if we could consider building it in Typescript directly.
My gut is that this is a hard sell. I might be even less interested in TS than @CrossEye given my experience working with it professionally in the past.
In addition to my practical concerns, TS doesn't support HKT's (though there are some workarounds) and last I checked compose couldn't be typed correctly.
Ramda doesn't have the correct ergonomics to really be a solid player in TS IMO. If I were to build a TS native library it might look quite different, and I think a number of people have been working on it.
If I were to build a TS native library it might look quite different, and I think a number of people have been working on it.
I've enjoyed watching fp-ts and have taken a number of ideas from it for a separate project I'm working on.
Apologies for my confusing wording, yes I actually meant to rewrite ramda in typescript.
I understand if main contributors are not really interested in this,
I just thought that would be a great deal for driving adoption.
Libraries that are type safe are also genereally easier to adopt.
Ramda doesn't have the correct ergonomics to really be a solid player in TS IMO.
I think it'd be difficult to port ramda to TS, but not impossible.
and last I checked compose couldn't be typed correctly
As any function that takes rest-like arguments, also compose is difficult to type in TS, and therefore needs a lot of manual typing... but that's okay I guess!
Anyway,
I appreciate the authors point of view, and happy to not proceed with this.
However, I'd like to also move the focus on the user's standpoint. I really think that for typescript developers, as well as javascript developers, having ramda typed safely would represent a big game changing choice.
That's why I came up with options 3. Write native javascript code with typedefs alongside. Write tests which are allowed to used a (very) limited subset of type definition syntax that is common to Typescript and flow (e.g. const value: Type = ...;). Then you can run your test files with javascript (use @babel/plugin-transform-flow-strip-types), and type check them with typescript (and/or flow). Thus if your typedefs don't permit a common usage, you'll know.
@conartist6: That's interesting. Might we also be able to simply keep a collection of TS test files designed only to check that the function types are right? That is, could we move test to test/js and add test/ts and test/flow that are processed with whatever @babell configuration is necessary? I don't know enough about TS or Flow testing to know if this makes sense. But it would be a cleaner breakdown: Update source and test/js for functionality changes. Update the TS typing file and test/ts for TS typing changes, and something similar for Flow.
@hitmands:
Apologies for my confusing wording,
Not at all. I simply saw what I wanted to see, overlooking an important word. :smile:
Ramda doesn't have the correct ergonomics to really be a solid player in TS IMO.
I think it'd be difficult to port ramda to TS, but not impossible.
I'm not sure what it would entail. I don't really know TS well. But do you think that it could be written in such a way that it would break absolutely nothing? What would happen to the types for functions that don't map into the TS world -- as it seems compose might not?
However, I'd like to also move the focus on the user's standpoint. I really think that for typescript developers, as well as javascript developers, having ramda typed safely would represent a big game changing choice.
That's why I wouldn't mind moving the typing files in-house, if we had someone who wanted to maintain them. But this so far has been a library written for JS developers by JS developers. We didn't try hard to ensure CoffeeScript compatibility, we don't spend any effort worrying about how it might work with ClojureScript, PureScript, or Elm, and we haven't put in significant effort toward TypeScript or Flow. Part of this is just a worry about the Flavor of the Month. But it's more than that; it's that this was designed to be a fairly low-level JS library. Anything else has to come second.
This exchange was posted in the javascript channel of https://functionalprogramming.slack.com today, and seems quite relevant:
Enrico Polanski
may I ask why many people do fp in js rather when a frendlier version in ts might be available?(honest question, not criticism, I just like being assisted by a compiler) (edited)
masaeedu
Depends on what you consider to be friendlier I guess. You need a bunch of hacks to implement features that have been outstanding issues for yearswell, "implement" I should say, you can't really implement these type system features inside the type system properly
Enrico Polanski
such as?ts does suffer with some polymorphic functions
but generally it's expressive and quite good at infering if you know how to get around it
masaeedu
higher kinded types, polymorphism in covariant positions, equirecursive types, inference of function parameter types from function body, metaprogrammingsolomon
does typescript have iso-recursive types? why would you want equi-recursive over iso-recursive?masaeedu
equirecursive is a lot more convenient than iso-recursive, and without compiler-solved typeclasses it's doubly inconvenient to use an iso-recursive encodingmasaeedu
you can go look at the average typescript fp library and compare the quantity of ugly type boilerplate to actual code that's doing something
>James Sinclair
I find the same thing with Flow.masaeedu
if you know how to get around itI got tired of getting around it
Enrico Polanski
well, it takes lots of time to get used to its quirksmasaeedu
well, I used it from ~2014 to ~2018 before I gave upmaybe it takes more time
Serhii Kyrychenko
What's wrong with @types/ramda ? Isn't it well typed?Enrico Polanski
plenty of things in ramda are untypeable in tse.g. type safe curry
try to have your ts compiler infer correctly the curry of this function:
f: <A,B> (a: A, b: B) => [A,B]Serhii Kyrychenko
Do we want to support named (not only ordered) currying?b => a => [a, b]? What ifAandBtypes have not empty intersection - how do we know if it wasborainf(x)?
I'm not sure what it would entail. I don't really know TS well. But do you think that it could be written in such a way that it would break absolutely nothing?
Yes, of course, typescript is just a js superset... a valid javascript file is also a valid typescript file.
What would happen to the types for functions that don't map into the TS world -- as it seems compose might not?
As said above, everything from js maps to ts. Some typings can result verbose, as the compose case where you would need to manually type every possible function call... You can look at how compose has been typed in redux, or any other library.
That's why I wouldn't mind moving the typing files in-house, if we had someone who wanted to maintain them. But this so far has been a library written for JS developers by JS developers. We didn't try hard to ensure CoffeeScript compatibility, we don't spend any effort worrying about how it might work with ClojureScript, PureScript, or Elm, and we haven't put in significant effort toward TypeScript or Flow. Part of this is just a worry about the Flavor of the Month. But it's more than that; it's that this was designed to be a fairly low-level JS library. Anything else has to come second.
This doesn't only help ts developers, any fairly modern IDE (wstorm, vscode) would automatically infer typings if present. This works in js as well as typescript (vs code doc). This really improves the overall user experience.
and I also agree with most of the masaeedu's points, but still think that Ramda is doable in typescript.
This is how it would look like (pseudo-code):
interface Map {
<A, B>(fn: (a: A) => B, list: A[]): B[]
<A, B>(fn: (a: A) => B): (list: A[]) => B[]
}
const map: Map = (fn, list) => list.map(fn);
currying (etc.) would require a bit of manual typing, but nothing undoable imho!
Yeah it's not too bad to type compose that way. iter-tools does as well. But it's also not a typedef you could ever infer from native typescript.
Typedefs for the flat method actually illustrate several of the problems. First, overloads like those with shouldFlat are wholly beyond typescript's expressiveness. Second, any additional parameters to the function would now double the number of lines needed. This is a serious maintenance cost to go through all the lines and make sure nothing is missed, and there's also no way to test all those definitions except by writing a test case for each line of the typedef. To keep things spiraling completely out of control we only allow a single partial application in our typescript types. That is to say, never (A) => (B) => (S) => R, only (A, B) => (S) => R and (A, B, S) => R.
The biggest problem you have with the as-native typescript design though is that it doesn't work at all unless you write a correct and usable type for the curry method. As far as I can tell this is impossible.
I think all this just drives home that you can't design a library like this for (or in) typescript. You can make best effort typedefs which are quite useful, but you are still designing for JS.
I think all this just drives home that you can't design a library like this for (or in) typescript. You can make best effort typedefs which are quite useful, but you are still designing for JS.
That concisely says what I've often tried to convey about Ramda's relationship to TS.
I'm curious if those who know TS well could tell me whether -- if we clean up our H-M typings to avoid all the ellipses -- we could generate everything needed for TS from them. Is that just a pipe-dream?
This is how it would look like (pseudo-code):
interface Map {
<A, B>(fn: (a: A) => B, list: A[]): B[]
<A, B>(fn: (a: A) => B): (list: A[]) => B[]
}
const map: Map = (fn, list) => list.map(fn);
I think this illustrates the issue pretty well. Let's take this initial interface as a starting point and try to get at maps actual type here.
The first thing I see is that this interface only deals with Array where in actuality map does so much more than that. Say we have an Object{A} or a Maybe(A) or a SomeOtherFunctor(A) so now we have a generic container type (let's call it Functor) and this generic container also has generic contents (A). map needs to be able to take an F of A's and a function from A to B and return an F (the same type, not an arbitrary Functor) of B's regardless of what the concrete type of F or A are, so long as F is a Functor.
From my understanding, TS can't do this without a lot of effort / workarounds. Neither of the current Ramda type definitions get it right from what I can see, though not for lack of trying.
But this so far has been a library written for JS developers by JS developers.
I think it'd be difficult to port ramda to TS, but not impossible.
I think it would be impossible for an exact port, but I do think we could get relatively close. I just don't know why we would. As @CrossEye has mentioned, this is a library that was designed for JS. I agree that a type file would be a boon for Typescript developers, but I don't see changing the implementation language as being beneficial to anyone. It would limit the amount of developers comfortable contributing, especially as it has already been acknowledged that typing the sorts of functions Ramda offers is hard and often the results are difficult to read and difficult to get right.
The first thing I see is that this interface only deals with Array where in actuality map does so much more than that. Say we have an Object{A} or a Maybe(A) or a SomeOtherFunctor(A) so now we have a generic container type (let's call it Functor) and this generic container also has generic contents (A). map needs to be able to take an F of A's and a function from A to B and return an F (the same type, not an arbitrary Functor) of B's regardless of what the concrete type of F or A are, so long as F is a Functor.
type Functor<T> = Array<T> | { [key: string]: T };
interface MAP {
<A, B>(fn: (a: A) => B): (functor: Functor<A>) => Functor<B>;
<A, B>(fn: (a: A) => B, functor: Functor<A>): Functor<B>;
}
declare var foo: MAP;
const list = foo(() => 'hi', [1, 2, 3]);
const obj = foo(() => 'hi')({ a: 1, b: 2, c: 3 });
I am not saying that porting ramda in typescript would be easy,
I am just saying that is doable...
Currying would need to be done manually, as the MAP example above...
Algebraic Data Structures should be created manually (ts supports unions and intersections)
this is a library that was designed for JS
I was saying that also JS developers would benefit from it since any modern IDE supports ts declarations in js too.
If a full porting is not to be considered,
then what about what @CrossEye said about in-housing ts declarations?
@hitmands: But note that there are plenty of other Functors out there. Function is a functor parameterized by the return type. Most implementations of Maybe, Either, Future/Task and many more are functors and users can define their own. So we would need a much more robust definition of Functor, presumably matching that of FantasyLand.
If a full porting is not to be considered, then what about what @CrossEye said about in-housing ts declarations?
That strikes me as much more reasonable. But that means finding someone who can do this interested in a longish-term commitment to maintaining it as Ramda progresses. The current core team simply does not have the requisite skills. Ideally there should be more than one, but if we found one person, we could get going and see if others would join.
Are you that person? I've seen your answers on StackOverflow and your reasonable discussions here. I would certainly be willing to put your name before the group to be another committer if you are interested in working on this.
I'm also still really curious if we could automate a conversion from better-disciplined versions of our current Hindley-Milner style typings. That would be the best of both worlds.
note that there are plenty of other Functors out there
Hey @CrossEye, of course there are... mine was an example, and yes we would Functor to ideally match FantasyLand...
__
Are you that person? I've seen your answers on StackOverflow and your reasonable discussions here. I would certainly be willing to put your name before the group to be another committer if you are interested in working on this.
I'd love that,
I use Ramda, I love it and I'd certainly like to help to make it more robust.
I'm also still really curious if we could automate a conversion from better-disciplined versions of our current Hindley-Milner style typings. That would be the best of both worlds.
I am not aware of any converter and I'd find difficult to imagine one :)
@hitmands:
I use Ramda, I love it and I'd certainly like to help to make it more robust.
Great. I'll discuss it with the group and get back to you soon.
I'm also still really curious if we could automate a conversion from better-disciplined versions of our current Hindley-Milner style typings. That would be the best of both worlds.
I am not aware of any converter and I'd find difficult to imagine one :)
Well, if I find the time, once you have some typings completed, I'll take a look to see what we might manage. Because that would be a great win!
I think this went stale and can be probably closed
Hmmm... stale? It would still be a cool project to convert ramda to TypeScript, I think. The typings on DefinitelyTyped are still limited in some ways, e.g. not all functions can work with __ there. And in the meantime TypeScript has some cool features for functional programming, there's things like Parameters<T>, which constructs a tuple type of the types of the parameters of a function type T. It would still be a project with adding alll the types, setting up the tooling, and would change how the code looks like. But it would also be super awesome to have accurate types for ramda 🎉
@bxt:
I'm thinking that would be more of a fork than a change. I'm quite sure that I'm not alone among the Ramda core team who's not interested in maintaining Ramda in TS.
I haven't paid a great deal of attention lately; has Typescript advanced far enough that it can support all the features that Ramda includes? It hasn't always done so.
I see, in this case I think I'd rather have a well-maintained ramda then one in TypeScript. I have to admit, I also don't know wether TypeScript would 100% support all of ramda's features atm. I guess the only way to find out is indeed to create a fork and try it 🙂 At the moment I don't have the time to really do that either, so I guess feel free to close the issue.
Found a related issue, the TypeScript keyword type is used in a few places https://github.com/ramda/ramda/issues/3028#issuecomment-635786696
This means if we want to compile it with tsc we would need to fix these
It isn't just used in the codebase. type is a top level function on the public API.
How is this being handled with the existing typings for Ramda that are out there?
... and how do we make the call about when to do such changes? How widespread does another library / language / tool have to be for Ramda to make accommodations to work with it? Does it matter how close it is in spirit to Ramda? Does it depend only on how hard it is to make those accommodations?
Hard questions.
I think in order to move forward this we would need to hammer out some practical concerns around this proposal.
While we tend to have a bit of bikeshedding around the PRs themselves, it's fairly straightforward to get a PR up. Ramda was the first OS project I contributed to. It's important to me personally that the codebase remains accessible - much of my professional life has been working with junior and self taught developers and I like that our process is straightforward enough for anybody to follow. I don't know if this is a priority for other maintainers.
For reference, here is our current contributing page: https://github.com/ramda/ramda/blob/master/CONTRIBUTING.md.
A first step would be to work out how we would need to change that document. If the change involves needing to write up typings for the function in Typescript, I fear I may no longer be qualified to contribute to a library I've been maintaining for the last 5 or so years.
curry but I don't know enough to say. The type concerns for a library like this are significantly different than the concerns with writing application level code in Typescript.I think this point has been fairly well covered, but I just want to be sure we have a strategy for when we can't safely type a function. How good is good enough? How do we communicate the differences?
My bottom line is that while I think that adding types would benefit Typescript developers, this isn't just a library for Typescript developers. I am a solid no on migrating to Typescript as an implementation language, and ambivalent on adding the typings in house separate from the implementation.
My thought as to process is that updating the typing file would be a requirement of a release process, not a more regular commit process. When preparing a release, a maintainer would have to check that the new or updated functionality is expressed in the typings file. This might fall fairly heavily on those maintainers who have a deeper TS understanding. but for simpler things, I imagine most of us can figure it out. It should be easy to see if a new function is included, or an old one properly removed. But when we update behavior, that might get harder.
Perhaps we can add a specific team (a subgroup of maintainers, along with other interested folks) and add something like this to CONTRIBUTING.md:
- If your change alters the public API, please either also update the [typings file][link here] yourself or in your Pull Request, ping (new team link here) to request help with this.
Not having that complete may or may not stop us from merging the PR, but it would definitely stop us from publishing it.
(Of course the discussion on the Deno thread about using GH commits as the source of truth might make this more difficult, too.)
The reasons I am a yes on bringing the typings in-house are (1) the number of support requests we seem to get for them, even though they haven't been ours to maintain, and (2) the fact that we have recent additions to the core team enthusiastic about keeping up with that support.
I needed some time to gather my thoughts around this.
I am not sure about type safety not being a pr requirement,
this would compromise overall type safety quality and/or put too much burden on
a few maintainers that would need to catch up with how the codebase evolves.
On the other side,
I totally agree with @Bradcomp as this requirement would compromise contribution accessibility...
I think we should find a way of unblocking this,
I really think that lack of ts support would eventually harm adoption...
Perhaps,
we should wait a bit,
or use a fork as a prof of concept?
I am not sure about type safety not being a pr requirement, this would compromise overall type safety quality and/or put too much burden on a few maintainers that would need to catch up with how the codebase evolves.
I think the only reason we are even considering doing this is that there are new maintainers excited by this. Ramda has always been a JS library, and I cannot imagine requiring an understanding of another language in order to contribute.
I suggested not publishing until the typings were straightened out, but I can also imagine simply not merging until then. If the contributor does not have the skills, then it might require corrections or additions from the core team before we merge it. But somehow we need to allow any JS developer to offer contributions.
Perhaps, we should wait a bit, or use a fork as a prof of concept?
Maybe, but I would think the first step would simply to create our own version of the typings file used by TS. That is what I assume would need to be changed on every API-altering commit. If we can't create one that captures the library as it stands, then we will have to see if the projects is even worth doing.
I would love to see a POC that could at least handle our example code. If we can do that I think that it would be feasible to move the typings in house.
I have been thinking more about this, and there are two main places where I see things coming up:
My trepidation on this comes from trying to add additional safety guarantees to the library before in the form of Property Based Tests. I still think they are a great way to guarantee our library against certain classes of bugs. I went through the work of adding PBTs to a number of Ramda functions that could benefit from them, as well as pushing for people to add them during PRs, and offering guidance on how to do that. Unfortunately my efforts didn't really pick up steam, and I think the tests I added are still the only ones in the codebase.
This is fine for PBTs because they don't effect the API, they just give us additional guarantees that our functions are total, or at least have a well defined domain and codomain. But with these typings we would be adding something that has an external effect, and will generate additional work if they are wrong or go out of date. It seems like much more of an all or nothing proposition.
Hello!
As someone that likes type-safety provided by tooling, I stumbled upon this discussion. I am not at all qualified to take part in this discussion, but it _seems_ to me like some of the mentioned hurdles will be resolved with a future major release of TypeScript. See here:
https://devblogs.microsoft.com/typescript/announcing-typescript-4-0-beta/
I hope this is actually relevant and not missing the point of this discussion entirely.
Hi, for instance which ones @PunkIslamist?
Hey @hitmands!
Sorry, just posting a link was very unspecific. The first feature described in the post seemed relevant to the discussion - variadic tuple types. They say that it can resolve the problem of escalating overloads. They also show a way to implement a generic partialCall() method with this feature.
I hope this clears it up a bit :)
I hope this is actually relevant and not missing the point of this discussion entirely.
I only read through that first section, but it did seem relevant. This could be very good news for those interested in Ramda with complete and accurate TS typings. I don't know TS well enough to see if that covers all the gap that currently exists, but it looks like it will at least reduce that gap.
Hi, for instance which ones @PunkIslamist?
Hello, any advancement on that issue. Are you still working on typescript support? I would like to help.
Hi @denismaxim0v ,
yes, there is a lot of interest on providing a safe ts experience,
we are deciding what the first steps will be.
So far, I think we are going to :
I would love to see a POC that could at least handle our example code. If we can do that I think that it would be feasible to move the typings in house.
I was also thinking to reach out to the authors of @types/ramda and @types/npm-ramda and see if there is interest in using their versions as starting points.
@hitmands Those sound like great first steps. I think a POC is the way to go, and reaching out to either or both of those projects seems easier than starting from scratch.
@hitmands Oh, great. Will look into these two for now then
I would also be on board to help if needed, I could really use the 4.0 support for TS
Great, so those are the packages:
I have emailed the authors and waiting for a feedback to plan next steps :)
Go Team!
Thanks for the notice. Basically, the approach behind npm-ramda is to use the codegen to generate the actual types from the type templates (e.g., the R.map type template and its generated type) to avoid writing those complex types manually. It worked mostly, the main issue is that TypeScript does not support HKTs, users will get errors if they'd like to use HKTs, or users can disable strictFunctionTypes to suppress those errors with the cost of getting not-that-accurate types. I'm still waiting TS to add such support so that we could get 100% type-accuracy, but I guess it should be enough accurate for most people to use for now.
As a passionate ramda and TypeScript user, I would love to see this happening!
Also might be able to offer a bit of help. I started using TypeScript quite recently, but I have background in Java and C# development. I prefer having strongly typed codebase and I used to work with quite complex hierarchies of generics.
Honestly, I hated JavaScript in the beginning, for not being strict enough, so migration to TypeScript is a huge improvement for me.
@CrossEye also, sorry for offtopic, but this caught my attention - is it posible to somehow apply for an invitation to FP Slack, which you mentioned? (functionalprogramming.slack.com)
@malyzeli:
@CrossEye also, sorry for offtopic, but this caught my attention - is it posible to somehow apply for an invitation to FP Slack, which you mentioned? (functionalprogramming.slack.com)
I'm sure it is. I must have done so several years ago, but I'm afraid I don't recall the process.
@ikatyang:
the main issue is that TypeScript does not support HKTs
I don't know enough about TS to understand if the recent updates will fix that:
https://devblogs.microsoft.com/typescript/announcing-typescript-4-0-beta/. Do you know?
Sorry for the late response. TS 4.0 improves it a lot, for example it is now possible to "carry" the generics with tuple types (i.e., you can think of that the tuple type can now be generic, though you cannot explicit specify it, they can only be inferred using infer), I'm not sure if it can solve all the issues but it should significantly improve the type accuracy here.
And also, there is an upcoming TS feature (currently scheduled at TS 4.1) called Template Literal Type, which can do more magic things, someone even uses it to write a type-level JSON parser. I'm not that good at meta-programming but maybe someone can use it to improve the type accuracy here.
I agree, that not all challenges can be solved by TypeScript alone, especially at runtime. But in addition to comment above I would like to highlight some points, of which not all js and ts developers are aware. First of all, the type system is very powerful. It's damn crazy powerful and you can damage the whole earth if you shot with it in your foot. The second one and more important: editors pick up typings even for plain javascript. It means that if a project has typings (or better: written in ts), then it makes both ts and js dev happier.
@Bessonov checkout Zod if you are interested in parsing schemas at runtime and using static types based on those schemas in your code - does that make sense?
In my eyes the core of the issue can be summed up in the following code block:
compose(toUpper, prop('name')) // => Error underneath prop('name')
The error message provided to the user:
No overload matches this call.
The last overload gave the following error.
Argument of type '<T>(obj: Record<"name", T>) => T' is not assignable to parameter of type '(x0: unknown, x1: unknown, x2: unknown) => string'.
Types of parameters 'obj' and 'x0' are incompatible.
Type 'unknown' is not assignable to type 'Record<"name", string>'.ts(2769)
To make the code work is quite simple:
// Conceptual
compose(toUpper, prop<Key, Value>('name'))
// General
compose(toUpper, prop<string, string>('name'))
// Specific
compose(toUpper, prop<'name', string>('name'))
The reason the error occurs is not due to an error of Typescript, Ramda or the type definitions. prop('name') cannot know what it is operating on if it is partially applied unless the user defines it and the only sensible way to do that is through generics. We are expecting too much of the type inference engine and too little of the person writing the software.
// Relevant type defintion
function prop<P extends keyof T, T>(p: P, obj: T): T[P];
// Code
prop('name', {name: 'Bill Bryson'}) // => <"name", {name: string}> types inferred
prop<'name', {name: string}>('name', {name: 'Bill Bryson'}) // => equivalent to above
// Relevant type definition
function prop<P extends string>(p: P): <T>(obj: Record<P, T>) => T;
// Code
prop('name')({name: 'Bill Bryson'}) // => <'name'><Record<'name', string>>
prop<'name'>('name')<Record<'name', string>>({name: 'Bill Bryson'}) // => equivalent to above
// Relevant type definition
function prop<P extends string, T>(p: P): (obj: Record<P, T>) => T;
// Code
compose(toUpper, prop('name'))
// In this example prop('name') is resolving to prop<'name', unknown>('name')
// toUpper expects a string, not unknown, therefore the compiler throws a warning
This quote from the Typescript Documentation sums up the issue:
_Point-free programming — heavy use of currying and function composition — is possible in JavaScript, but can be verbose. In TypeScript, type inference often fails for point-free programs, so you’ll end up specifying type parameters instead of value parameters. The result is so verbose that it’s usually better to avoid point-free programming._
With all that being said generics are a great way of keeping code concise and I feel the benefits of point-free programming are worth having to manually set types in certain circumstances.
The issue for me is not the language Ramda is written in, nor is it (for the most part) an issue with the typings. The issue is the complete lack of documentation (outside of source code) detailing how to apply generics to enable point-free programming. I completely understand why this is as Ramda is a Javascript library and I don't think it is the responsibility of the maintainers of @types/ramda either. For that reason, I am currently going through each Ramda function and adding notes on how the typings could be improved as well as writing documentation detailing how to use that specific functions generics.
For example:
filter@generic Input [set] - if you're passing number[] this should be set as number
const ages = [56, 30, null]
const names = ['Bill', 'Bob']
// Untyped
const filterAges = filter(Boolean)
filterAges(names) // => silent error
// Typed
const filterAges = filter<number>(Boolean)
filterAges(names) // => Typescript warning
isNilThis is just my alternative view but I do think any re-write has an huge opportunity cost, not a lot of benefit and misses the core of the issue which is a lack of documentation. I may be missing something but that is my take on the issue and if anyone else is in agreement I would love a bit of help writing up the documentation which could then potentially be added as a link on the home page.
I totally agree with what you said,
I'd just add one thing though:
The issue between point free programming and ts generics
doesn't really represent a limitation, it only leads to a more verbose code in my opinion.
Still something that should not prevent us from delivering a great developer experience,
especially nowadays that ts adoption is constantly improving (e.g. _deno_, etc.)

@alexandermckay:
That looks wonderful. When you're done, do you see this as suggesting changes to Ramda -- more JSDoc tags? Separate documentation? -- or to a Ramda typings document? Or do you see this as an eventually independent of both?
@CrossEye separate documentation for the time being and potentially long term as well.
Most helpful comment
I would also be on board to help if needed, I could really use the 4.0 support for TS