I implemented a function (let's call it valuesOfThings) that takes an object with arbitrary key names and values of a specific object type Thing (effectively a Map). The function should then return an object with the same keys, but the value for each key should be the value of some key of Thing.
For example I want to convert this:
const things = {
someThing: { value: 10 },
otherThing: { value: 'foo'},
}
to this:
const values = {
someThing: 10,
otherThing: 'foo',
}
and I want the returned object to be typed correctly.
The JS implementation of the function looks like this:
function valuesOfThings(things) {
const values = Object.fromEntries(
Object.entries(things)
.map(([key, thing]) => [key, thing.value])
// ^^^^^^^^^^^----- the important part
)
return values
}
Based on this question I managed to craft the following return type:
{[key in keyof T]: T[key] extends Thing<infer ValueType> ? ValueType : never}
Let's see it in action:
type Thing<T> = {
value: T
}
type ThingMap = {
[key: string]: Thing<unknown>
}
function valuesOfThings_1<T extends ThingMap>(things: T): {[key in keyof T]: T[key] extends Thing<infer ValueType> ? ValueType : never} {
const values = Object.fromEntries(
Object.entries(things)
.map(([key, thing]) => [key, thing.value])
)
return values as {[key in keyof T]: T[key] extends Thing<infer ValueType> ? ValueType : never}
}
As you can see, the return type is relatively lengthy and has to be repeated when returning. But at least it results in the correct type and when I hover the returned variable, I see the type I expected:
Bu when I try to extract this type like so:
type ThingValuesMap<T> = {
[key in keyof T]: T[key] extends Thing<infer ValueType> ? ValueType : never
}
function valuesOfThings<T extends ThingMap>(things: T): ThingValuesMap<T> {
return Object.fromEntries(
Object.entries(things)
.map(([key, thing]) => [key, thing.value])
) as ThingValuesMap<T>
}
the resulting type is not correctly resolved:
However, the intellisense knows the correct types:
As you can see, the type of otherThing is correctly displayed as string.
I've created a TS playground here. Hover values_1 and values_2 to see the difference.
Why is the type not displayed correctly when extracting the return type? Am I doing something wrong here?


