juxt calls an array of functions to return an array of values. Docs: ramda clojure
I'm trying to type a data-first version of this without overrides, but I can't figure out how to map the tuple of functions to their return values. This is what I have:
type JuxtFn<T> = (x: T) => any
function juxt<T, Fs extends JuxtFn<T>[]>(
x: T,
fns: Fs,
): {[K in keyof Fs]: ReturnType<Fs[K]>} {
return fns.map(fn => fn(x))
}
It complains (among other complaints)
Type 'Fs[K]' does not satisfy the constraint '(...args: any) => any'.
Is this possible in TypeScript?
CodePudding user response:
I'm not sure why the ReturnType
isn't working. Here's an alternative, however:
type JuxtFn<T> = (x: T) => any
function juxt<T, FS extends readonly JuxtFn<T>[]>(
x: T,
fns: FS,
) {
return fns.map(fn => fn(x)) as unknown as { [K in keyof FS]: FS[K] extends (x:any)=>infer X ? X : never}
Full playground here. Does that help?
CodePudding user response:
Consider using function overload for this case:
type JuxtFn<T> = (x: T) => any
function juxt<T, Fn extends JuxtFn<T>, Fns extends Fn[]>(
x: T,
fns: [...Fns],
): { [K in keyof Fns]: Fns[K] extends Fn ? ReturnType<Fns[K]> : never }
function juxt<T, Fs extends JuxtFn<T>[]>(
x: T,
fns: Fs,
) {
return fns.map(fn => fn(x))
}
// [string[], Promise<number>]
const result = juxt(
10,
[(v: number) => ['s'], (v: number) => Promise.resolve(42)]
)
I have added conditional type Fns[K] extends Fn ? ReturnType<Fns[K]> : never
just to assure TypeScript that Fns[K]
is a function
You can find more information about infering return type of [].map
here. This was merged and then reverted.