Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Infer parameter types in function chain

I'm trying to make a home made function mapping chain. Thing is, I want to make sure typing stays consistent trough the mapping chain. My problem is that I don't know how to write f(x:T) => U

For a proper example of what I'm trying to do:

function myChainer<T>(args:T){
    return {
       map:(innerFuction:(payload: T) => unknown){
           return myChainer(innerFuction(args))
       }
    }
}

Now, if I run

myChainer(0)
.map((args1) => {
    return doSomething(args1) ? "a" : "b"
})
.map((args2) => {
    return doSomething2(args2) ? true : false
})

The first map will know that the type of args1 is Number but the second one wont know that the type of args2 is string. And, as expected, subsequent chained functions wont know the types of their respective arguments. With what should unknown be replaced with so that every chained function figures out the type of its arguments based on the return type of the previously chained function?

like image 747
Axel Avatar asked Jun 26 '26 04:06

Axel


2 Answers

You need to use a generic type parameter to refer to whatever the return type of the innerFunction is, so that you can then provide that type to TS when you recursively refer to myChainer.

Here is what that would look like:

function myChainer<T>(args:T){
    return {
       map<U>(innerFuction:(payload: T) => U) {
           return myChainer<U>(innerFuction(args))
       }
    }
}
like image 63
GregL Avatar answered Jun 28 '26 18:06

GregL


Here you have:


function myChainer<T>(args: T) {
    return {
        map: <R,>(innerFuction: (payload: T) => R) => {
            return myChainer(innerFuction(args))
        }
    }
}

const foo = (arg: number) => arg.toString()
const bar = (arg: string) => Promise.resolve(parseInt(arg, 10))
const baz = (arg: Promise<number>) => arg


const result = myChainer(0)
    .map(arg => foo(arg)) // arg -> number
    .map(arg => bar(arg)) // arg -> string
    .map(arg => baz(arg)) // arg -> Promise<number>
    .map(arg => foo(arg)) // expected error
like image 30
captain-yossarian Avatar answered Jun 28 '26 17:06

captain-yossarian



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!