TypeScript Version: 2.5.3
Code
function weird<T extends Record<string, { x: any }>>(o: T) {
type Additional = T & { extra: { x: number } }
type XValues = { [K in keyof Additional]: Additional[K]['x'] }
const results: XValues = undefined as any // implementation not important
return results
}
const results = weird({
foo: { x: 'hello' },
bar: { x: true },
})
Expected behavior:
The type of results should be
{
foo: string;
bar: boolean;
extra: number;
}
and was, prior to 2.5.3.
Actual behavior:
The type of results is
{
[K in keyof (T & {
extra: {
x: number;
};
})]: (T & {
extra: {
x: number;
};
})[K]["x"];
}
I'm not even sure what that type means, since it contains the free variable T that only existed in the scope of the function that produced the result. T should've resolved to { foo: { x: 'hello' }, bar: { x: true } }.
This is a minimal repro whittled down from a much larger body of code in our app, and the problem is preventing us from being able to migrate beyond TypeScript 2.5.2.
Interestingly, this reformulation using a WithAdditional type constructor makes it resolve correctly:
type WithAdditional<T> = T & { extra: { x: number } }
function weird<T extends Record<string, { x: any }>>(o: T) {
type XValues = { [K in keyof WithAdditional<T>]: WithAdditional<T>[K]['x'] }
const results: XValues = undefined as any // implementation not important
return results
}
const results = weird({
foo: { x: 'hello' },
bar: { x: true },
})
// results: {
// foo: string;
// bar: boolean;
// extra: number;
// }
This is a duplicate of #19043. I will have a fix up soon.
Duplicate of #19043
GitHub has a first-class notion of issue duplication now, but apparently you have to be very specific in your wording :)
Most helpful comment
GitHub has a first-class notion of issue duplication now, but apparently you have to be very specific in your wording :)