Giter Club home page Giter Club logo

"#<Object> is not a constructor" when used with TypeScript's `allowSyntheticDefaultImports` & `esModuleInterop` about promise.allsettled HOT 17 CLOSED

es-shims avatar es-shims commented on May 26, 2024 18
"# is not a constructor" when used with TypeScript's `allowSyntheticDefaultImports` & `esModuleInterop`

from promise.allsettled.

Comments (17)

borekb avatar borekb commented on May 26, 2024 6

For anyone needing a quick workaround, here's a TypeScript function emulating the behavior.

Note: It's probably not as generic & correct as this lib's implementation but works fine for the use case I have.

export function allSettled<T>(iterable: Iterable<Promise<T>>): Promise<PromiseResult<T>[]> {
  const arr = Array.from(iterable, item => {
    return item
      .then(value => ({ status: 'fulfilled', value } as PromiseResolution<T>))
      .catch(reason => ({ status: 'rejected', reason } as PromiseRejection<typeof reason>));
  });
  return Promise.all(arr);
}

// Types are taken from
// https://github.com/DefinitelyTyped/DefinitelyTyped/blob/1d3c224/types/promise.allsettled/types.d.ts

export interface PromiseResolution<T> {
  status: 'fulfilled';
  value: T;
}

export interface PromiseRejection<E> {
  status: 'rejected';
  reason: E;
}

export type PromiseResult<T, E = unknown> = PromiseResolution<T> | PromiseRejection<E>;

export type PromiseTuple<T extends [unknown, ...unknown[]]> = { [P in keyof T]: Promise<T[P]> };
export type PromiseResultTuple<T extends [unknown, ...unknown[]]> = { [P in keyof T]: PromiseResult<T[P]> };

from promise.allsettled.

gauthierm avatar gauthierm commented on May 26, 2024 5

As a workaround I was able to call the shim method and then use the Promise.allSettled API instead of calling allSettled directly.

from promise.allsettled.

mikevinmike avatar mikevinmike commented on May 26, 2024 4

Had the same issue and fixed it with using .call() on allSettled function:
await allSettled.call(Promise, [...]);

from promise.allsettled.

borekb avatar borekb commented on May 26, 2024 3

Ok, I'm no expert on this but created this TS issue anyway: microsoft/TypeScript#35420.

Thank you for all the info, @ljharb.

from promise.allsettled.

joshverd avatar joshverd commented on May 26, 2024 3

I fixed this issue by using an import require.

import allSettled = require('promise.allsettled');

from promise.allsettled.

Narretz avatar Narretz commented on May 26, 2024 1

It was reverted because of a performance regression: microsoft/TypeScript#35877 (comment)

microsoft/TypeScript@cb9cd89

from promise.allsettled.

ljharb avatar ljharb commented on May 26, 2024

The TypeScript module system is broken unless both of those settings are enabled; they should be enabled in every project, full stop (and tsc init enables them in all new projects too)

If typescript’s downleveling is incorrect, you’ll have to file an issue with them - I’d suggest using babel for all transpilation, and only use tsc as a typechecker.

from promise.allsettled.

ljharb avatar ljharb commented on May 26, 2024

If there’s something that can change in the types (which i don’t maintain) I’d be happy to review and endorse a PR to DefinitelyTyped.

from promise.allsettled.

borekb avatar borekb commented on May 26, 2024

I agree with the general comment that Babel should be preferred over tsc for transpiling but we cannot make that change right now.

Back to the original issue, the typings are correct but the runtime behavior isn't. This is plain JS demonstrating the issue:

const allSettled = { default: require("promise.allsettled") };

const resolved = Promise.resolve(42);
const rejected = Promise.reject(-1);

allSettled.default([resolved, rejected]).then(results => {
  console.log(results);
});

Output:

TypeError: [object Object] is not a constructor
    at Object.resolve (<anonymous>)
    at Object.PromiseResolve (/home/runner/node_modules/es-abstract/es2018.js:160:10)
    at /home/runner/node_modules/promise.allsettled/implementation.js:26:24
    at Function.from (<anonymous>)
    at Object.allSettled (/home/runner/node_modules/promise.allsettled/implementation.js:19:22)
    at Object.allSettled [as default] (/home/runner/node_modules/promise.allsettled/index.js:16:9)
    at /home/runner/index.js:10:19    at Script.runInContext (vm.js:133:20)
    at Object.<anonymous> (/run_dir/interp.js:156:20)    at Module._compile (internal/modules/cjs/loader.js:778:30)

Playground.

from promise.allsettled.

ljharb avatar ljharb commented on May 26, 2024

hmm, I think i see what you mean.

This is due to the behavior here: https://github.com/es-shims/Promise.allSettled/blob/master/index.js#L16 combined with the actual spec behavior for Promise.allSettled, which uses the this.

In other words, the downleveling is indeed incorrect, since it should not be calling the default function with a receiver - it should be something like (0, allSettled.default)([resolved, rejected]), which will ensure its receiver is undefined.

There's no way for me to fix things here without violating the spec; this is indeed a bug in TypeScript's downleveling.

from promise.allsettled.

borekb avatar borekb commented on May 26, 2024

How about exporting the implementation that doesn't re-bind this? I'd do something like this:

import { allSettled } from 'promise.allsettled/implementation';

from promise.allsettled.

ljharb avatar ljharb commented on May 26, 2024

That already exists under /implementation, but then it will fail because it's not Promise.

In other words, it seems like what you want is an implementation that always ignores the receiver and sets it to Promise. You could do allSettled.call(null, [resolved, rejected]) i suppose, and that should work even with the broken tsc output, while you wait for TS to fix it? (assuming you file an issue for them)

from promise.allsettled.

borekb avatar borekb commented on May 26, 2024

Thanks, that's a good-enough workaround.

I'm not sure how to formulate that TypeScript issue, if it's an issue at all as they've been generating the current __importDefault code for a long time and quickly searching their issues doesn't seem like there would be any problems with it. But I'm not sure about the details.

from promise.allsettled.

ljharb avatar ljharb commented on May 26, 2024

That’s probably just because very few packages have modules that take advantage of this this behavior. Babel does it, and is often much more correct than typescript is, so that’s the example I’d suggest they follow.

from promise.allsettled.

ljharb avatar ljharb commented on May 26, 2024

This appears to be fixed in the next version of TypeScript.

from promise.allsettled.

alexandrucancescu avatar alexandrucancescu commented on May 26, 2024

This still throws the same error when used with the last typescript version 4.2.3

import allSettled from "promise.allsettled";

allSettled([Promise.resolve(1), Promise.reject("")]);

Results in:

TypeError: #<Object> is not a constructor at Object.allSettled (<anonymous>) at Object.allSettled [as default]

tsconfig:

{
  "compilerOptions": {
    "lib": ["ES2019"],
    "module": "commonjs",
    "target": "ES2019",
    "outDir": "dist",
    "sourceMap": true,
    "declaration": true,
    "experimentalDecorators":true,
    "emitDecoratorMetadata": true,
    "moduleResolution": "node",
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true
  }
}

from promise.allsettled.

ljharb avatar ljharb commented on May 26, 2024

@alexandrucancescu yes, because the fix isn't released yet. The next version of TypeScript will fix it.

from promise.allsettled.

Related Issues (9)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.