Skip to content
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

Object.values creates variables implicitly typed as any with no warning, even with noImplicitAny #49857

Closed
guillaumebrunerie opened this issue Jul 11, 2022 · 4 comments

Comments

@guillaumebrunerie
Copy link

Bug Report

In some cases, Object.values creates variables implicitly typed as any without any warning, even though noImplicitAny is set to true.

🔎 Search Terms

Object.values, any, noImplicitAny

🕗 Version & Regression Information

  • This is the behavior in every version I tried (including 4.8.0 beta in the Playground), and I reviewed the FAQ for entries about any/unknown/Object.values

⏯ Playground Link

Playground link with relevant code

💻 Code

declare const obj : {[key: string]: string} | {[key: string]: number}

for (const v of Object.values(obj)) {
    v.a.b.c = 42; // No error or warning, v has type any
}

🙁 Actual behavior

v has type any even though I never wrote any myself and set the noImplicityAny option to true.

🙂 Expected behavior

Ideally v should have type string | number, but at the very least it should either have type unknown or trigger an "implicit any" warning.

@MartinJohns
Copy link
Contributor

MartinJohns commented Jul 11, 2022

The signature of Object.values() returns an explicit any (intentionally), there's nothing implicit. Changing it to unknown would be a massive breaking change, which IMO would be pointless, as this method is explicitly for dealing with dynamic data. But I understand the sentiment, tho it would be a feature request instead of a bug.

@guillaumebrunerie
Copy link
Author

Note that Object.values does not always return an explicit any. For instance if its argument is of type {[key: string]: (string | number)} (to which the type in my original example is assignable), then it does return (string | number)[] as I would expect:

declare const obj : {[key: string]: string} | {[key: string]: number}

const obj2: {[key: string]: string | number} = obj;

for (const v of Object.values(obj2)) {
    v.a.b.c = 42; // Error: Property 'a' does not exist on type 'string | number'.
}

This made it particularly surprising to me as I used Object.values several times before without having to deal with any, but suddenly I have an any appearing just because my variable happens to be of a union type.
Maybe the non-any type signature of Object.values could be refined to also deal with union types properly?

Also, I would argue that unknown is the correct type for dealing with dynamic data, but I agree that it could be a big breaking change.

@MartinJohns
Copy link
Contributor

Note that Object.values does not always return an explicit any. For instance if its argument is of type {[key: string]: (string | number)} (to which the type in my original example is assignable), then it does return (string | number)[] as I would expect:

That's true, I always forget that, because it really shouldn't do that. It should always return any or unknown. See #38520.

@guillaumebrunerie
Copy link
Author

Ah, thank you for the link, makes perfect sense now, I didn’t realize this type was actually inconsistent. I guess I'll try to avoid Object.values from now on 😄

@guillaumebrunerie guillaumebrunerie closed this as not planned Won't fix, can't repro, duplicate, stale Jul 11, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants