Skip to content

Change in behavior around keyof any inference #29765

New issue

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

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

Already on GitHub? # to your account

Closed
mike-north opened this issue Feb 6, 2019 · 1 comment
Closed

Change in behavior around keyof any inference #29765

mike-north opened this issue Feb 6, 2019 · 1 comment
Assignees
Labels
Bug A bug in TypeScript Fixed A PR has been merged for this issue

Comments

@mike-north
Copy link

mike-north commented Feb 6, 2019

TypeScript Version: 3.4.0-dev.20190202

Search Terms: any, array, argument

Code

function getProps<T, K extends keyof T>(obj: T, list: K[]): Pick<T, K> {
    return {} as any;
}

const myAny: any = {};


// TS 3.2.2 - getProps returns Pick<any, "foo" | "bar">
// TS 3.4   - getProps returns Pick<any, "foo" | "bar">
const o1 = getProps(myAny, ['foo', 'bar']);

// TS 3.2.2 - getProps returns Pick<any, "foo" | "bar">
// TS 3.4   - getProps returns Pick<any, string>
   // └ 🚨 Type 'Pick<any, string>' is missing the following properties
   //   from type '{ foo: any; bar: any; }': foo, bar [2739]
const o2: { foo: any; bar: any } = getProps(myAny, ['foo', 'bar']);

Expected behavior:

I expect o2 above to type-check successfully in 3.4

Actual behavior:

Playground Link: NOTE: does not demonstrate the reported behavior, since it's only reproducible in recent 3.4 nightly builds

https://www.typescriptlang.org/play/index.html#src=function%20getProps%3CT%2C%20K%20extends%20keyof%20T%3E(obj%3A%20T%2C%20list%3A%20K%5B%5D)%3A%20Pick%3CT%2C%20K%3E%20%7B%0D%0A%20%20%20%20return%20%7B%7D%20as%20any%3B%0D%0A%7D%0D%0A%0D%0Aconst%20myAny%3A%20any%20%3D%20%7B%7D%3B%0D%0A%0D%0A%2F%2F%20TS%203.2.2%20-%20getProps%20returns%20Pick%3Cany%2C%20%22foo%22%20%7C%20%22bar%22%3E%0D%0A%2F%2F%20TS%203.4%20%20%20-%20getProps%20returns%20Pick%3Cany%2C%20string%3E%0D%0Aconst%20o2%3A%20%7B%20foo%3A%20any%3B%20bar%3A%20any%20%7D%20%3D%20getProps(myAny%2C%20%5B'foo'%2C%20'bar'%5D)%3B%0D%0A%0D%0A%2F%2F%20TS%203.2.2%20-%20getProps%20returns%20Pick%3Cany%2C%20%22foo%22%20%7C%20%22bar%22%3E%0D%0A%2F%2F%20TS%203.4%20%20%20-%20getProps%20returns%20Pick%3Cany%2C%20%22foo%22%20%7C%20%22bar%22%3E%0D%0Aconst%20o3%20%3D%20getProps(myAny%2C%20%5B'foo'%2C%20'bar'%5D)%3B%0D%0A

Related Issues: #29698 #25759

@ahejlsberg
Copy link
Member

Looks like this is an effect of #29478. Previously we'd make no inferences from the return type in the second example, but now we infer from { foo: any; bar: any } to Pick<T, K>. This produces an inference for K, but not for T because Pick<T, K> isn't a homomorphic mapped type (it's partially homomorphic in that it only maps a subset of the properties). Because we have no candidates for T, we end up with an inference of {} from the return type, which then causes us to reduce our inference for K to never. We then proceed with this rather useless contextual type which ends up making matters worse rather than better.

Looks like we need to do better when inferring to Pick<T, K>. I will see what we can do.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
Bug A bug in TypeScript Fixed A PR has been merged for this issue
Projects
None yet
Development

No branches or pull requests

2 participants