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

Allow TypeScript to infer the type of a Future created by node() from its callback #375

Open
Avaq opened this issue Sep 26, 2019 · 2 comments

Comments

@Avaq
Copy link
Member

Avaq commented Sep 26, 2019

node(done => open('somefile', 'r', done)) doesn't infer the callback value type since open returns nothing we can use as a reference. typeof open however can give some information.

so given this signature:

open(a: string, b: string, cb: (er: Error | null, fd: number) => void): void

we can find out its return type using the new infer keyword:

type TypeOf<T extends (a: any, b: any, cb: (er: Error | null, value?: any) => void) => void> = T extends (
  a: any,
  b: any,
  cb: (er: Error | null, value?: infer R) => void
) => void
  ? R
  : any

example:

declare function open(path: string, flags: string | number, callback: (err: Error | null, fd: number) => void): void
type T1 = TypeOf<typeof open>
// number (fd)

with that we can infer the callback type:

import { FutureInstance } from 'fluture'

declare function node<F extends (cb: (er: Error | null, value?: any) => void) => void>(
  f: F
): F extends (cb: (er: infer L, value?: infer R) => void) => void ? () => FutureInstance<NonNullable<L>, R> : () => any
declare function node<F extends (a: any, cb: (er: Error | null, value?: any) => void) => void>(
  f: F
): F extends (a: infer A, cb: (er: infer L, value?: infer R) => void) => void
  ? (a: A) => FutureInstance<NonNullable<L>, R>
  : (a: any) => any
declare function node<F extends (a: any, b: any, cb: (er: Error | null, value?: any) => void) => void>(
  f: F
): F extends (a: infer A, b: infer B, cb: (er: infer L, value?: infer R) => void) => void
  ? (a: A, b: B) => FutureInstance<NonNullable<L>, R>
  : (a: any, b: any) => any
declare function node<F extends (a: any, b: any, c: any, cb: (er: Error | null, value?: any) => void) => void>(
  f: F
): F extends (a: infer A, b: infer B, c: infer C, cb: (er: infer L, value?: infer R) => void) => void
  ? (a: A, b: B, c: C) => FutureInstance<NonNullable<L>, R>
  : (a: any, b: any, c: any) => any

import { open, close } from 'fs'

const t1 = node(open)
// (a: PathLike, b: string | number) => FutureInstance<NodeJS.ErrnoException, number>
const t2 = node(open)(__dirname + '/bla', 'r')
// FutureInstance<NodeJS.ErrnoException, number>
const t3 = node(close)
// (a: number) => FutureInstance<NodeJS.ErrnoException, unknown>

rest of the family

declare function map<A, B>(f: (a: A) => B): <L>(fa: FutureInstance<L, A>) => FutureInstance<L, B>

declare function double(n: number): number

const t4 = map(double)
// <L>(fa: FutureInstance<L, number>) => FutureInstance<L, number>

const t5 = t4(node(open)(__dirname + '/../../package.json', 'r'))
// FutureInstance<NodeJS.ErrnoException, number>

declare function of<A>(a: A): FutureInstance<never, A>

declare function ap<L, A>(fa: FutureInstance<L, A>): <B>(fab: FutureInstance<L, (a: A) => B>) => FutureInstance<L, B>

const t6 = ap(of(42))
// <B>(fab: FutureInstance<unknown, (a: number) => B>) => FutureInstance<unknown, B>

const t7 = t6(of(a => a + 'world'))
// FutureInstance<unknown, string>

const t8 = ap(map(double)(node(open)(__dirname + '/../../package.json', 'r')))(of(a => a + 'world'))
// FutureInstance<NodeJS.ErrnoException, string>

Originally posted by @tetsuo in #374 (comment)

@Avaq
Copy link
Member Author

Avaq commented Sep 26, 2019

I think what we might do is reintroduce the encaseN function. I had removed it because it's easily expressible using compose (node), but as you note, TypeScript cannot infer the type from a call to node.

@tetsuo
Copy link
Contributor

tetsuo commented Sep 26, 2019

@Avaq Avaq changed the title Allow the Node function to infer the type of the callback Allow TypeScript to infer the type of a Future created by node from its callback Oct 24, 2019
@Avaq Avaq changed the title Allow TypeScript to infer the type of a Future created by node from its callback Allow TypeScript to infer the type of a Future created by node() from its callback Oct 24, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants