Reputation: 21
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
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