There are times when I encounter this issue without understanding why the inference fails.
Specifically, zip
behaves correctly when directly used, but not when used within pipe
, leaving me puzzled.
declare const zip: {
<A, B>(input: readonly [readonly A[], readonly B[]]): [A, B][],
<A, B, C>(input: readonly [readonly A[], readonly B[], readonly C[]]): [A, B, C][],
<A, B, C, D>(input: readonly [readonly A[], readonly B[], readonly C[], readonly D[]]): [A, B, C, D][],
<A extends readonly any[]>(input: readonly A[]): A[0][][],
};
declare const pipe: <A, B>(a: A, f: (a: A) => B) => B;
declare const x: [number[], string[], boolean[]];
const foo = pipe(x, zip);
// ^? foo: any[][]
const bar = pipe(x, x => zip(x))
// ^? bar: [number, string, boolean][]
playground It's not that big of a deal, but it really confuses me as it can lead to wasted time and effort trying to figure out compilation errors or typing issues.
As a side note, the pipe
function mentioned is a more complex version that is typically found in functional programming libraries but does not work in certain scenarios like the one described.
const pipe: {
<A>(
a: A
): A
<A, B>(
a: A,
f: (a: A) => B
): B
<A, B, C>(
a: A,
f: (a: A) => B,
g: (b: B) => C
): C
// More function overloads...
}
You might think that a mapped type could address this issue, but it seems to only work for monomorphic functions. Experimenting with simpler designs still leads to indirection that confuses the compiler.
Feel free to share insights on the zip
situation and thoughts on the more complex version of pipe
.