I’m making a function in TS which provides the equivalent functionality of Array.prototype.map() for dictionaries (objects within which all of the values share the same type). The function itself works just fine:
// Array.prototype.map, but for Dict
function mapDict<T, M>(dict: Dict<T>, callback: (dictValue: T, dictKey: string, dict: Dict<T>) => M): Dict<M> {
const mappedDict: Dict<M> = {}
for (let keyValPair of Object.entries(dict)) {
const mappedVal: M = callback(keyValPair[1], keyValPair[0], dict);
mappedDict[keyValPair[0]] = mappedVal;
}
return mappedDict;
};
However, what I’m struggling to understand is the following. In the typed function declaration above, we explicitly say that the second argument mapDict should take is a callback function which takes three arguments (none of which are optional) and returns a type which is cast onto our second generic type M. Bearing that in mind, why does TS not complain when I do this:
const fruits = {
apple: { color: "red", mass: 100 },
grape: { color: "red", mass: 5 },
banana: { color: "yellow", mass: 183 },
lemon: { color: "yellow", mass: 80 },
pear: { color: "green", mass: 178 },
orange: { color: "orange", mass: 262 },
raspberry: { color: "red", mass: 4 },
cherry: { color: "red", mass: 5 },
}
interface Dict<T> {
[k: string]: T
}
const mappedDict = mapDict(fruits, (fruit) => {
// return {
// ...fruit,
// kg: 0.001 * fruit.mass
// }
});
As you can see, in the above invocation of mapDict, the callback I’ve passed in as an argument only has one argument / identifier, whereas I’ve explicitly stated it must receive three, and yet TS is totally fine with it. If I had to make a guess as to what’s going on here, I would say that TS what is actually enforcing is how many arguments are passed into the callback when the callback is invoked, and in the code above, the callback is always invoked with three arguments which adheres to the way we typed it. While that does somewhat make sense, it still confuses me that we explicitly tell TS “this argument must be a function that takes receives three arguments / identifiers”, and yet there are no complaints if we provide a function that only takes one.
Could somebody explain more clearly the behaviour that’s occurring here?