You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Spinning this out of tc39/proposal-hack-pipes#18 (thanks @OliverJAsh). He raised an important point: that rx.pipe, etc. currently work with but would not work with Hack pipes (or F# pipes?).
We need to document this in the explainer in an FAQ.
To be clear, this is not due to any inherent mathematical property of Hack pipes.
This is a manifestation of a limitation of TypeScript’s current inference algorithm: it can only unify types from left to right, and it cannot unify types in expressions like map(i => i + 1)(items).
Indeed, this limitation is why RxJS and Ramda must use a brittle workaround for their pipe functions: they manually overload the arity of their pipe functions up to a finite number. For example, RxJS manually overloads the arity of rx.pipeten times:
As can be seen, this means that rx.pipe only supports automatic TypeScript inference when piping a value through less than nine functions; more than ten functions would require manual typing.
Again, this is not due to any inherent mathematical property of Hack pipes. In fact, this probably would not work with F# pipes either. It is the result of not being able override the arity of a pipe operator and to specify the type of each arity, as RxJS does above (and as Ramda, etc. do too).
The amazing TypeScript team has been working hard on a new, more robust type inferencer: one that improves its type unification so that it retains free types (microsoft/TypeScript#30134). But of course this means that we can’t do map(i => i + 1)(items) today, and we therefore can’t do items |> map(i => i + 1)(^) today. (I’m sorry that Hack pipes don’t give a good answer to this now—other than to manually annotate types as needed (which TypeScript developers often already have to do) and hope for microsoft/TypeScript#30134 to land.)
In any case, the explainer does not talk about this. This is a deficiency of the explainer. We need to fix this sometime.
This issue tracks the fixing of this deficiency in the explainer (lack of discussion regarding TypeScript’s current limitations). Please try to keep the issue on topic (e.g., comments about the importance of tacit programming would be off topic), and please try to follow the code of conduct (and report violations of others’ conduct that violates it to [email protected]). Please also try to read CONTRIBUTING.md and How to Give Helpful Feedback. Thank you!
The text was updated successfully, but these errors were encountered:
If it's useful to anyone. The following utility function can wrap a function so that the receiver can be passed as the first argument, which currently works better for TypeScript inference.
functionmap<V,R>(f: (v: V)=>R){returnfunction(arr: Array<V>): Array<R>{returnarr.map(f);}}map(v=>v+1)([1,2,3]);// no inference, 'v' is 'unknown' ❌const_map=uncurryReceiver(map);_map([1,2,3],v=>v+1);// 'v' is inferred as 'number' ✅
Uh oh!
There was an error while loading. Please reload this page.
Spinning this out of tc39/proposal-hack-pipes#18 (thanks @OliverJAsh). He raised an important point: that
rx.pipe
, etc. currently work with but would not work with Hack pipes (or F# pipes?).We need to document this in the explainer in an FAQ.
To be clear, this is not due to any inherent mathematical property of Hack pipes.
This is a manifestation of a limitation of TypeScript’s current inference algorithm: it can only unify types from left to right, and it cannot unify types in expressions like
map(i => i + 1)(items)
.This is an incidental TypeScript limitation, about which @OliverJAsh has been raising issues for several years (see microsoft/TypeScript#15680, as well as the related microsoft/TypeScript#22081, microsoft/TypeScript#25826, microsoft/TypeScript#29904, microsoft/TypeScript#30134).
Indeed, this limitation is why RxJS and Ramda must use a brittle workaround for their
pipe
functions: they manually overload the arity of their pipe functions up to a finite number. For example, RxJS manually overloads the arity ofrx.pipe
ten times:As can be seen, this means that
rx.pipe
only supports automatic TypeScript inference when piping a value through less than nine functions; more than ten functions would require manual typing.Again, this is not due to any inherent mathematical property of Hack pipes. In fact, this probably would not work with F# pipes either. It is the result of not being able override the arity of a pipe operator and to specify the type of each arity, as RxJS does above (and as Ramda, etc. do too).
The amazing TypeScript team has been working hard on a new, more robust type inferencer: one that improves its type unification so that it retains free types (microsoft/TypeScript#30134). But of course this means that we can’t do
map(i => i + 1)(items)
today, and we therefore can’t doitems |> map(i => i + 1)(^)
today. (I’m sorry that Hack pipes don’t give a good answer to this now—other than to manually annotate types as needed (which TypeScript developers often already have to do) and hope for microsoft/TypeScript#30134 to land.)In any case, the explainer does not talk about this. This is a deficiency of the explainer. We need to fix this sometime.
This issue tracks the fixing of this deficiency in the explainer (lack of discussion regarding TypeScript’s current limitations). Please try to keep the issue on topic (e.g., comments about the importance of tacit programming would be off topic), and please try to follow the code of conduct (and report violations of others’ conduct that violates it to [email protected]). Please also try to read CONTRIBUTING.md and How to Give Helpful Feedback. Thank you!
The text was updated successfully, but these errors were encountered: