Property 'entries' does not exist on type 'ObjectConstructor'

53,883

Solution 1

You're quite correct that changing target is the wrong approach and changing lib is the correct approach, however you have specified the wrong version of the language. According to MDN, Object.entries was officially added in the ES2017 specification.

"lib": ["es2017"]

is therefore what you must specify instead*.

If you wish to add only the declarations for the methods of the Object function that were added in ES2017, TypeScript allows you to specify a more granular value.

"lib": ["es2017.object"]

As noted by Alexander Bird, by default, the implicit value of the "lib" option is dependent on the value specified for "target" if present.

For example:

"target": "es2017"

Will cause the correspondingly prefixed "lib.*" to be included by default unless "lib" is specified explicitly.

Note that you will likely wish to add a polyfill of the implementation itself, such as the this one, to ensure this works in older runtimes.

Note: as an alternative you can specify any later version

"lib": ["es2020"]

or naturally even

"lib": ["esnext"] 

This last will include the declarations for the very latest standard library features known to the TypeScript language. As it represents a moving target, this option should be used with care since polyfilling all of the corresponding runtime is by definition a complex task that will require research and may involve loading different polyfills depending on your target runtime.

Additionally, the array nature of the "lib" option allows you to combine multiple values to match your runtime. For example, to match es2015 capable web browsers with the addition of these object methods as provided by a polyfill, you can write

"lib": ["es2015", "es2017.object", "dom"]

See the TypeScript Handbook for additional details.

Note: a few commenters asked why it would be wrong to change --target instead of --lib as both would enable the code to type check? The reason is that --target changes how the code is transpiled. For example, "target": "es2017" means that async functions won't be transformed for older runtimes. It is incorrect because the intent was to enable the use of additional libraries, not to change the output syntax and it is therefore important to distinguish between syntactic features and library features.

Solution 2

The accepted answer didn't work for me, but I adapted the answer from Property 'assign' does not exist on type 'ObjectConstructor' like this:

const changedFields = (<any>Object).entries(this.ngForm.form.controls)
                                   .filter(value => value[1].dirty);

Sharing for anyone with the same situation

Share:
53,883
user8334943
Author by

user8334943

Updated on September 05, 2021

Comments

  • user8334943
    user8334943 over 2 years

    I'm working on an ng2 implementation. I'm using the following function call to convert an object to an array:

    var authors = Object.entries(responseObject.Authors);
    

    This is a standard js function. However, the ts compiler returns the following error:

    "Property 'entries' does not exist on type 'ObjectConstructor'"
    

    Based on a quick google it appears that the solution may be to change the compilerOptions target property from es5 to es6. However, after some previous research for a previous issue, I thought that I was able to leverage es6 functionality by including the additional "lib" property on my tsconfig.json below:

      "compilerOptions": {
        "emitDecoratorMetadata": true,
        "experimentalDecorators": true,
        "module": "commonjs",
        "noEmitOnError": true,
        "noImplicitAny": false,
        "outDir": "../Scripts/",
        "removeComments": false,
        "sourceMap": true,
        "target": "es5",
        "moduleResolution": "node",
        "lib": [
          "es2015",
          "dom"
        ]
      }
    

    I also tried changing the target property to es2015 and then rebuilt the project and executed "typescriptUsingTsConfig" but I still get the same error. Any idea what I can do here in order to leverage the Object.entries() function?

  • user8334943
    user8334943 almost 7 years
    thanks aluan. that does the trick. would this be supported by ie10+? trying to figure out whether or not I should add a polyfill
  • Aluan Haddad
    Aluan Haddad almost 7 years
    @user8334943 no you will definitely need a polyfill for IE 10. The MDN link has browser support information at the bottom.
  • alexanderbird
    alexanderbird over 6 years
    Note for others: if you didn't use lib compiler option already, there may have been a default value based on your target that will be overridden when you set lib. See the compiler options documentation for the list of defaults. I had to explicitly add the default lib parameters for my target as well as es2017.object.
  • Jessy
    Jessy over 6 years
    what version of typescript is es2017 available in?
  • Jessy
    Jessy over 6 years
    It worked fine (after restarting vs code) "@angular/cli": "^1.4.9",, "@angular/core": "^4.2.4" and "typescript": "^2.3.4".
  • Jessy
    Jessy over 6 years
    @AluanHaddad for sure :) I agree with keeping updated as long as possible and I'll be performing the update soon. This is a large application, with many developers so updating needs to be planned. Thanks for your input!
  • rjh
    rjh over 5 years
    Why is it more correct to update lib instead of target?
  • Aluan Haddad
    Aluan Haddad over 5 years
    @rjh Target changes how the code is transpiled. For example, "target": "es2017" means that async functions won't be transformed for older runtimes. It is incorrect because the intent was to enable the use of additional libraries, not to change the output syntax.
  • Irrfan23
    Irrfan23 almost 5 years
    I am getting error while writing Unit tests for Object.entries(), error message is "undefined is not a constructor". In my typescript file its working fine without any errors, target : 'es5', lib: [es2017, dom].
  • Aluan Haddad
    Aluan Haddad almost 5 years
    @Irrfan23 that's a runtime error, it's not TypeScript related. I'd need to see code to understand since entries doesn't involve constructors.
  • Irrfan23
    Irrfan23 almost 5 years
    @AluanHaddad its not runtime error, this error was persisting because es6 does not support Object.entries(). I just import entries from es7 in my olyills.ts file and it worked.
  • Aluan Haddad
    Aluan Haddad almost 5 years
    @Irrfan23 which demonstrates that it's a runtime error.
  • MichaelE
    MichaelE almost 4 years
    Thanks Nguyen......I am using Angular 6 with typescript 2.6.2 and this is what worked for me. I would love if someone could explain it.
  • Julian Suggate
    Julian Suggate almost 4 years
    worked for me in the typescript playground. that's some serious voodoo
  • Luis Antonio Canettoli Ordoñez
    Luis Antonio Canettoli Ordoñez over 3 years
    And always remember to RESTART your VSCode after this!
  • Aluan Haddad
    Aluan Haddad over 3 years
    In the typescript playground, you can't currently set --lib so you have to use --target to specify --lib implicitly
  • David Fariña
    David Fariña over 3 years
    You're a hero. I couldn't change the lib because it is generated by another application where I don't have the possibility to change tsconfig.