Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Request: Infer generics #30887

Open
babakness opened this issue Apr 12, 2019 · 4 comments
Open

Request: Infer generics #30887

babakness opened this issue Apr 12, 2019 · 4 comments
Labels
Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature Suggestion An idea for TypeScript

Comments

@babakness
Copy link

The request is to let infer support generics.

Background:

I recently published a recursive Pipe and Compose. It offers some key advantages, including the preservation of variable names.

https://github.com/babakness/pipe-and-compose-types

Its shortcoming is in the case of generics. This is because infer does not work well with generics. Example

/**
 * Extracts function arguments
 */
export type ExtractFunctionArguments < Fn > = Fn extends  ( ...args: infer P ) => any  ? P : never

/**
 * Extracts function return values
 */
export type ExtractFunctionReturnValue<Fn> = Fn extends  ( ...args: any[] ) => infer P  ? P : never

type Foo = ExtractFunctionArguments< <A>(a:A, b:number) => A >
// Foo has type [ {} , number ]

TypeScript 3.4 improved how pipe and compose functions work with generics with higher order type inference from generic functions.

Common implementations of pipe and compose rely on parameter overloading. However, even here, there is an issue with variadic functions. See example in this issue:

#30727

The broader issue with the parameter overloading version of pipe and compose is that parameter names are lost, decreasing code clarity. The recursive version, relying on infer does maintain parameter names.

Providing support generics with infer will present a major productivity bump and will nearly complete the community's need for the common place pipe and compose in FP patterns without compromise.

The only outlier is a small situation with parameter names on variadic functions of a minimum arity of zero as opposed to at least one. Can provide examples if needed since it is a separate issue.

@RyanCavanaugh RyanCavanaugh added Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature Suggestion An idea for TypeScript labels Apr 16, 2019
@tani
Copy link

tani commented May 1, 2019

I also faced this issue when I proposed new Curring interface to fp-ts (gcanti/fp-ts#843) . I write the following function alias.

export type CurriedN<A extends Array<unknown>, B> = A extends []
  ? () => B
  : A extends [unknown]
  ? ((...args: A) => B)
  : ((...args: A) => unknown) extends ((head: infer H, ...tail: infer T) => unknown)
  ? ((...args: [H]) => CurriedN<T, B>)
  : never

However, this alias drops generics parameter.

According to @gcanti ,

import { FunctionN } from 'fp-ts/lib/function'

export type CurriedN<A extends Array<unknown>, B> = A extends []
  ? () => B
  : A extends [unknown]
  ? ((...args: A) => B)
  : ((...args: A) => unknown) extends ((head: infer H, ...tail: infer T) => unknown)
  ? ((...args: [H]) => CurriedN<T, B>)
  : never

declare function curry2<A extends Array<unknown>, B>(f: FunctionN<A, B>): CurriedN<A, B>

declare function map<A, B>(as: Array<A>, f: (a: A) => B): Array<B>

const mapCurried2 = curry2(map)
// inferred type: mapCurried2: (args_0: {}[]) => (f: (a: {}) => {}) => {}[]

I also request this feature. Thank you.

@tani
Copy link

tani commented Nov 7, 2020

@RyanCavanaugh @babakness I confirm to work my example in v4.1.0-beta! We can close this issue. Cheers 🍻

@RyanCavanaugh RyanCavanaugh reopened this Nov 20, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

3 participants