Type predictions work only within pipe function

124 views Asked by At

I'm using monocle-ts (https://github.com/gcanti/monocle-ts) library in my project. I have the following code

import {id, prop} from 'monocle-ts/lib/Lens'
import {pipe} from 'fp-ts/function'

type State = {a: string, b: string}
const stateLens = id<State>()
const aLens = pipe(stateLens, prop('a'))

^ this code works perfectly fine, type system will not allow me to pass string that is not either 'a' or 'b'. However if I'm trying to write the same code in other way:

const aLens = prop('a')(stateLens)

I'm getting an error: Argument of type 'string' is not assignable to parameter of type 'never' Type definitions of prop function looks like this:

declare const prop: <A, P extends keyof A>(prop: P) => <S>(sa: Lens<S, A>) => Lens<S, A[P]>

I'm guessing that by using pipe-style typescript is somehow able to infer all generic parameters which is not the case for regular prop(...)(...) invocation

1

There are 1 answers

0
jboot On BEST ANSWER

The alternative notation you tried is a two-step process that first creates a lambda function using prop('a') and then immediately invoking it with ...(stateLens). The prop() function only receives a key name 'a', but cannot determine the object it belongs to as it only has the string parameter 'a' to work with. So, in the type definitions of prop the type A will be resolved to never because it's not assigned and cannot be inferred.

I didn't test this, but you probably can do the same by manually passing along the type like

prop<State, 'a'>('a')(stateLens)

but this is exactly what pipe does as it receives the State type from the its first parameter, and I think you can agree that in this case using pipe looks nicer.

So, you are right, pipe is able to infer the correct type and pass it to prop.