Skip to content

Inferred type does not resolve completely, contains free variables #19086

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
pelotom opened this issue Oct 10, 2017 · 4 comments
Closed

Inferred type does not resolve completely, contains free variables #19086

pelotom opened this issue Oct 10, 2017 · 4 comments
Labels
Duplicate An existing issue was already created

Comments

@pelotom
Copy link

pelotom commented Oct 10, 2017

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.

@pelotom
Copy link
Author

pelotom commented Oct 10, 2017

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;
// }

@ahejlsberg
Copy link
Member

This is a duplicate of #19043. I will have a fix up soon.

@ahejlsberg ahejlsberg added the Duplicate An existing issue was already created label Oct 11, 2017
@pelotom
Copy link
Author

pelotom commented Oct 11, 2017

Duplicate of #19043

@pelotom
Copy link
Author

pelotom commented Oct 11, 2017

GitHub has a first-class notion of issue duplication now, but apparently you have to be very specific in your wording :)

@pelotom pelotom closed this as completed Oct 12, 2017
@microsoft microsoft locked and limited conversation to collaborators Jun 14, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

2 participants