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

Unable to compile Object.fromEntries -- polyfill required #968

Closed
abhimanyuPathania opened this issue Feb 4, 2021 · 1 comment
Closed
Labels
kind: support Asking for support with something or a specific use case solution: intended behavior This is not a bug and is expected behavior solution: out-of-scope This is out of scope for this project

Comments

@abhimanyuPathania
Copy link

Current Behavior

I am building an NPM package for Node using the 'basic' template. I tried using Object.fromEntries in my code but get the error:

TypeError: Object.fromEntries is not a function

Upon inspecting the .cjs.development.js output it leaves Object.fromEntries untransformed which I guess are not supported in Node 10. I tried using build --target node which does not resolve it. Changing target on tsconfig also does not fix this.

Expected behavior

Typescript or Babel should be able to compile Object.fromEntries

Suggested solution(s)

Maybe a Babel plugin or polyfill is missing.

Additional context

Following is code snippet and transformed output
Code:

export default class Platform {
  id: string;
  name: string;
  channelLabelVsIdMap: Record<string, number>;
  features: Record<string, Feature | undefined>;

  constructor(platform: TPlatformMetadata, metadata: TMetadataResponse) {
    const { features = [] } = metadata;
    this.id = platform.id;
    this.name = platform.name;
    this.channelLabelVsIdMap = platform.channelLabelVsIdMap;

    this.features = Object.fromEntries(
      features
        .filter((feature) => feature.platformId === platform.id)
        .map((feature) => [feature.id, new Feature(feature, metadata)]),
    );
  }
}

Transformed output tsdx build

var Platform = function Platform(platform, metadata) {
  var _metadata$features = metadata.features,
      features = _metadata$features === void 0 ? [] : _metadata$features;
  this.id = platform.id;
  this.name = platform.name;
  this.channelLabelVsIdMap = platform.channelLabelVsIdMap;
  this.features = Object.fromEntries(features.filter(function (feature) {
    return feature.platformId === platform.id;
  }).map(function (feature) {
    return [feature.id, new Feature(feature, metadata)];
  }));
};

Your environment

  System:
    OS: macOS 10.15.3
    CPU: (8) x64 Intel(R) Core(TM) i7-4770HQ CPU @ 2.20GHz
    Memory: 792.30 MB / 16.00 GB
    Shell: 5.7.1 - /bin/zsh
  Binaries:
    Node: 10.22.0 - ~/.nvm/versions/node/v10.22.0/bin/node
    Yarn: 1.22.4 - /usr/local/bin/yarn
    npm: 6.14.6 - ~/.nvm/versions/node/v10.22.0/bin/npm
  Browsers:
    Chrome: 88.0.4324.96
    Firefox: 84.0.2
    Safari: 13.0.5
  npmPackages:
    tsdx: ^0.14.1 => 0.14.1
    typescript: ^4.1.3 => 4.1.3

@agilgur5 agilgur5 added the kind: support Asking for support with something or a specific use case label Mar 6, 2021
@agilgur5
Copy link
Collaborator

agilgur5 commented Mar 6, 2021

Problem Summary

So I looked this up and microsoft/TypeScript#32803 and vercel/next.js#16715 (comment) summarize this well.

Upon inspecting the .cjs.development.js output it leaves Object.fromEntries untransformed which I guess are not supported in Node 10. I tried using build --target node which does not resolve it.

Indeed, MDN reports this is as only compatible with Node 12+. I thought it was strange the --target node option didn't work for you because it will set @babel/preset-env to target Node 10 (and one or two other settings), but as those issues suggest, that's because Object.fromEntries has no transform, it must be polyfilled. TSDX does not set preset-env's useBuiltIns options as it is impure (pollutes global scope) and designed for apps not libraries.

Suggested Solution

TSDX currently leaves how to polyfill up to the library author as there are different preferences in the library ecosystem. But, what I'd suggest based on future state is to use babel-polyfills, specifically babel-plugin-polyfill-corejs3 with usage-pure set. Then I would suggest making core-js a dependency.
This should act similarly to useBuiltIns, but be pure and designed for libraries. TSDX recently switched to using a similar method to polyfill regenerator in #795 .

Future State

I would like to move to add the core-js Babel plugin polyfill by default in the future, but per my comments in that PR, there's some legwork to make sure TSDX can detect when you need a polyfill and make sure you have the respective polyfill listed as a dep (since TSDX is a devDep, a peerDep on it would not suffice, and not all users need to polyfill either). We currently bundle in regenerator-runtime if necessary which is suboptimal to using a dep (potential for duplicates), so it would apply for that polyfill and likely similar for @babel/runtime as well.

Changing target on tsconfig also does not fix this.

See #951 (comment) .
This is unsupported since we override to ESNext and transpile the rest with preset-env. Future state also includes having a warning for this 😅 (it's a somewhat common occurrence, along with downlevelIteration, importHelpers, etc).

@agilgur5 agilgur5 closed this as completed Mar 6, 2021
@agilgur5 agilgur5 added solution: intended behavior This is not a bug and is expected behavior solution: out-of-scope This is out of scope for this project labels Mar 6, 2021
@agilgur5 agilgur5 added this to the Future Non-breaking milestone Mar 6, 2021
@agilgur5 agilgur5 changed the title Unable to compile Object.fromEntries Unable to compile Object.fromEntries -- polyfill required Mar 6, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind: support Asking for support with something or a specific use case solution: intended behavior This is not a bug and is expected behavior solution: out-of-scope This is out of scope for this project
Projects
None yet
Development

No branches or pull requests

2 participants