Rico Kahler Rico Kahler - 3 months ago 16
TypeScript Question

How to get the implicit typing of function returns in TypeScript?

I'm experimenting with typescript and I'm trying to create a

using(...)
function that is basically an IIFE but with the arguments first instead of last.

var someValue = (function (p0, p1) {
// p0 is someGlobal
// p1 is someOtherGlobal

// do stuff with in scope

return /*something*/;
}(someGlobal, someOtherGlobal));


The above is the common IIFE with a return value. Again, I'm just experimenting here, but I think this would be more readable if the arguments of the IIFE came first then the function e.g.

const someValue = using([someGlobal, someOtherGlobal], /*as*/ (p0, p1) => {
// p0 is someGlobal p1 is someOtherGlobal
// do stuff
return /*something*/;
});


And this
using(...)
function doesn't seem to hard to write but now I'm having trouble typing this function for intellisense within VS code.

This is what I've come up with so far:

function using<A, B, C, D, E, F>(
params: A | [A, B] | [A, B, C] | [A, B, C, D] | [A, B, C, D, E, F],
func: (p0: A, p1: B, p2: C, p3: D, p4: E, p5: F) => any
) {
return func(
params[0],
params[1],
params[2],
params[3],
params[4],
params[5]
);
}


This function correctly types the parameters of
func
but what it doesn't do is type the return value. So in this example:

const someValue = 42;
const someNum = using(someValue, num => num + 1);


num
is correctly typed as a
number
but
someNum
is typed to
any
.

I think might be because I typed the return type of
func
to
=> any
.

So here's the question:

How do I get vs code to know the type of
someNum
?

typescript playground

Answer

I want to start by saying that this code is very unintuitive in my opinion, if anyone in the future will need to read and understand this code then he's in for a treat.

With that being said, the solution to what you're asking is very simple, it's just hard to see it with all of those generics, as the answer is just: add another generic type for the return type of the function:

function using<A, B, C, D, E, F, Return>(
    params: A | [A, B] | [A, B, C] | [A, B, C, D] | [A, B, C, D, E, F],
    func: (p0: A, p1: B, p2: C, p3: D, p4: E, p5: F) => Return
): Return {
    return func(
        params[0],
        params[1],
        params[2],
        params[3],
        params[4],
        params[5]
    );
}

const someNumber = 42;
const someString = 'whoo';
const someValue = using([someNumber, someString], (num, str) => {
    return num + str.length;
});

(code in playground)

The type of someValue is number.