-
-
Notifications
You must be signed in to change notification settings - Fork 84
Open
Description
node(done => open('somefile', 'r', done))
doesn't infer the callback value type sinceopen
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): voidwe 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 : anyexample:
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)
Metadata
Metadata
Assignees
Labels
No labels