eslint-plugin-functional icon indicating copy to clipboard operation
eslint-plugin-functional copied to clipboard

`functional/functional-parameters` Limit only to specific types

Open danielnixon opened this issue 1 year ago • 3 comments

Suggestion

When using functional/functional-parameters, we have ignorePrefixSelector but that can't tap into TypeScript type information.

There are a few places that I would love to whitelist in a way that requires type information. It would be great if we had that ability.

Here's one motivating example:

In https://github.com/gcanti/fp-ts, there are many cases where Lazy thunks are used to achieve functional purity.

One case is when lifting Promises (eager, not referentially transparent) into fp-ts TaskEithers (lazy, referentially transparent):

export declare const tryCatch: <E, A>(f: Lazy<Promise<A>>, onRejected: (reason: unknown) => E) => TaskEither<E, A>

When calling that, you are frequently taking some existing code that returns a Promise and doing this to it:

TE.tryCatch(() => existingCodeThatReturnsPromise);

That lazy thunk (() => ...) unfortunately triggers functional/functional-parameters, even though in this case we're writing code that in spirit is extremely functional.

Luckily, fp-ts defines Lazy like so:

export interface Lazy<A> {
  (): A
}

It could have defined it like export type Lazy<A> = () => A;, but for our purposes here we're lucky they made it a named interface.

If we could tap into the type information, we'd know that the contextual type of () => existingCodeThatReturnsPromise is actually Lazy<...> due to it being passed to TE.tryCatch (first param type being: f: Lazy<Promise<A>>). That would allow us to whitelist cases like this.

Note that fp-ts also defines a type IO<A> that is structurally the same as Lazy<A> but has different semantics: IO<A> is assumed to be impure. We would not want to whitelist IOs.

danielnixon avatar Mar 13 '23 00:03 danielnixon