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

Empty type inferred by Object.entries #21826

Open
salehe opened this issue Feb 9, 2018 · 16 comments
Open

Empty type inferred by Object.entries #21826

salehe opened this issue Feb 9, 2018 · 16 comments
Labels
Bug A bug in TypeScript Domain: lib.d.ts The issue relates to the different libraries shipped with TypeScript
Milestone

Comments

@salehe
Copy link

salehe commented Feb 9, 2018

TypeScript Version: 2.7.1

Search Terms: Object entries empty TS2365

Code

let o: any = {x: 5};

let p = Object.entries(o).map(([k, v]) => v + 1);

Compile command: tsc --lib es2017,es2017.object a.ts

Expected behavior:
This should compile without any error, assuming v: any.
This was the case for Typescript 2.6.2 at least.

Actual behavior:
(3,43): error TS2365: Operator '+' cannot be applied to types '{}' and '1'.

Following codes compile without errors:

let o: object = {x: 5};

let p = Object.entries(o).map(([k, v]) => v + 1);
let o: any = {x: 5};

let p = Object.entries(o).map(([k, v]: [any, any]) => v + 1);
@salehe salehe changed the title empty type inferred by Object.entries Empty type inferred by Object.entries Feb 9, 2018
@ghost
Copy link

ghost commented Feb 9, 2018

Looks like this is due to #20553. Previously the second overload of entries took any, now it takes {}. Previously we would match the second overload while now we match the first.

declare function values<T>(x: { [key: string]: T }): T[];
declare function values(x: any): any;

declare function values2<T>(x: { [key: string]: T }): T[];
declare function values2(x: {}): any;

values(a)[0].toUpperCase(); // No error
values2(a)[0].toUpperCase(); // Error

This behavior seems sort of strange so I'm wondering if it's intended.

@ghost
Copy link

ghost commented Feb 9, 2018

Talked with @sandersn and it looks like the problem would be fixed if we considered any to have an implicit index signature [key: string]: any in getImplicitIndexTypeOfType. (But we also have to make sure control flow gets there if the source type is any, so not quite as simple as that).

Currently the problem is that when choosing an overload we use a subtype relationship. any subtypes any but does not subtype {}, so after the change we end up choosing the first overload instead of the second.

@rhys-vdw
Copy link
Contributor

Just jumping in here... I also get a problem with this code:

  const x: Readonly<{ [id: number]: number }>  = { 5: 1 }
  const entries = Object.entries(x)

It must be Readonly and have a numeric key.

entries is incorrectly typed as const entries: [string, {}][]

@ghost
Copy link

ghost commented Mar 21, 2018

@rhys-vdw That looks like #22105 -- No problem with id: string.

@mhegazy
Copy link
Contributor

mhegazy commented Mar 28, 2018

I wounder if we should just get back to any. seems like our attempts to make it better have caused more trouble.

@mhegazy mhegazy added Bug A bug in TypeScript Domain: lib.d.ts The issue relates to the different libraries shipped with TypeScript labels Mar 28, 2018
@mhegazy mhegazy assigned ghost Mar 28, 2018
@mhegazy mhegazy added this to the TypeScript 2.9 milestone Mar 28, 2018
@salehe
Copy link
Author

salehe commented Mar 29, 2018

Actually my case was fixed in 2.8-rc but again happening in 2.8.1 .

@EliSnow
Copy link

EliSnow commented Apr 19, 2018

Can this issue be expanded so Object.keys(o) and Object.entries(o) return type for the keys is keyof typeof o, rather than just string?

@RyanCavanaugh
Copy link
Member

@EliSnow no, see #12253

@salehe
Copy link
Author

salehe commented May 17, 2018

So that you know, this is still an issue in 2.9 RC.

@ghost ghost added the Fixed A PR has been merged for this issue label Jun 5, 2018
@mhegazy mhegazy modified the milestones: TypeScript 3.0, Future Jul 2, 2018
@ghost ghost assigned sandersn and unassigned ghost Nov 16, 2018
@liamness
Copy link

liamness commented Apr 4, 2019

As a work-around, and building on the workaround for Object.keys() in this comment, I've just made one for Object.entries() too. Obviously only safe to use with objects that you have typed and know that these types can be relied upon.

export const entries = Object.entries as <T>(
  o: T
) => [Extract<keyof T, string>, T[keyof T]][]

edit: Looking at it more, I'm not sure Extract is required / desirable here. Seems to work fine without.

@RyanCavanaugh RyanCavanaugh added the Fix Available A PR has been opened for this issue label Jul 15, 2019
@saschanaz
Copy link
Contributor

saschanaz commented Oct 9, 2019

Can't reproduce this anymore, v is now any.

@Akxe
Copy link

Akxe commented Oct 9, 2019

@liamness Shouldn't the TS implementation of keys, values and entries implement overload for readonly/const objects, that would return the type that can be statically obtained?

@SKaistrenko
Copy link

We still see this issue in TS 3.5

@whbjzzwjxq
Copy link

e.g.
type item = 'node' | 'link' | 'media'                
let typeDict: Record<item, string[]> = {
                    node: [],
                    link: [],
                    media: []
                };
Object.entries(typeDict).map(([_type, labels]) => {
           **_type inferred as string but not item here**
})

@sandersn
Copy link
Member

I think reverting #20553 is the right thing (@saschanaz it still repros for me on master). @DanielRosenwasser do you agree?

@Akxe
Copy link

Akxe commented Dec 11, 2019

I think so too. It is very similar to how TS handles array[numberIndex] to not be undefined.

@sandersn sandersn removed their assignment Jan 7, 2020
@jakebailey jakebailey removed Fixed A PR has been merged for this issue Fix Available A PR has been opened for this issue labels Jun 21, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript Domain: lib.d.ts The issue relates to the different libraries shipped with TypeScript
Projects
None yet
Development

No branches or pull requests