ashish
ashish

Reputation: 21

Different return type inference for same implementation in typescript

I would like to understand why is there a type difference between the following 2 implementations. Both of them generate the same results but the return type for both of them varies.

const from = [
    () => console.log('first'), 
    () => console.log('second'), 
    () => console.log('third')];

const to = {
    first: 1,
    second: 2,
    third: 3,
};

const aggFn = (from: Function[], to: { [as: string]: any }): Record<keyof typeof to, Function> => {
    return ({
        first: from[0],
        second: from[1],
        third: from[2],
    } as unknown) as Record<keyof typeof to, Function>;
};

const agg = aggFn(from, to);

The return type of agg here is Record<"string" | "number", Function>, where as for the second code

const from = [
    () => console.log('first'), 
    () => console.log('second'), 
    () => console.log('third')];

const to = {
    first: 1,
    second: 2,
    third: 3,
};

const aggFn2 = <T>(from: Function[], to: { [as: string]: any }): T => {
    return ({
        first: from[0],
        second: from[1],
        third: from[2],
    } as unknown) as T;
};

const agg2 = aggFn2<Record<keyof typeof to, Function>>(from, to);

the return type is Record<"first" | "second" | "third", Function>

Upvotes: 0

Views: 67

Answers (1)

Jonas Wilms
Jonas Wilms

Reputation: 138247

The difference is that to in the two versions of typeof to refer to different variables: In the first snippet it refers to the local variable of type { [as: string]: any }, in the other one it refers to the global variable to. That variable was typed through the value assigned to it, which is of type { first: string, second: string, third: string }.

The actual typing of the function should be (which actually fits it's behaviour, and it allows typescript to infer the generic argument based on the to argument):

  <T> (to: Record<T, any>): Record<T, Function>

Upvotes: 1

Related Questions