1

Code is:

export class ExtendedMap<T, U> extends Map {
    constructor() {
        super();
    }

    toggle(key: T, value: U) {
        if (this.has(key)) {
            super.delete(key);
        } else {
            super.set(key, value);
        }
    }

    has(key: T): boolean {
        return super.has(key);
    }
}

I get this error for ES5 compilation:

ERROR TypeError: Constructor Map requires 'new'

I'm using it like this:

public registryLayers = new ExtendedMap<number, any>();

Snippet (without TypeScript parts commented out):

/*export*/ class ExtendedMap/*<T, U>*/ extends Map {
    constructor() {
        super();
    }

    toggle(key/*: T*/, value/*: U*/) {
        if (this.has(key)) {
            super.delete(key);
        } else {
            super.set(key, value);
        }
    }

    has(key/*: T*/)/*: boolean*/ {
        return super.has(key);
    }
}
/*public*/ registryLayers = new ExtendedMap/*<number, any>*/();
console.log("Worked without error");

12
  • 1
    I was just about to point out that Map wasn't in ES5. Also note that there's no point to either the constructor or the has override in your code. You can inherit both, since neither does anything new. It would also probably be best to use this rather than super in toggle. Commented Mar 2, 2021 at 11:32
  • 1
    Then you'll need a polyfill, because ES5 didn't have Map. Commented Mar 2, 2021 at 11:33
  • 1
    FWIW here's a playground link Commented Mar 2, 2021 at 11:37
  • 1
    @T.J.Crowder wow! I mean - WOOOOOW. I have never used Symbol.species before. I should have follow your answers a long time ago Commented Mar 2, 2021 at 12:07
  • 1
    @T.J.Crowder yes, I know, I saw it on your blog. This, defenitely, will be my next book. For now I have two others I did not finished yet )). I like that you went deeper into JS specification Commented Mar 2, 2021 at 12:25

1 Answer 1

6

TypeScript should be complaining about Map if you're targeting ES5 (it does in this example).

If you ignore that error from TypeScript and then run the code that TypeScript generates in a modern(ish) JavaScript engine, the problem is that the code TypeScript created is trying to call Map like an old-style constructor function. When you configure TypeScript to emit ES5 code, it doesn't emit class constructs because ES5 didn't have them. Instead, it emits constructor function syntax, and in your ExtendedMap constructor, it tries to call Map like this:

return _super.call(this) || this; // Where `_super` is set to `Map`

But in a modern environment, Map is defined as a class constructor and cannot be called that way, resulting in the error you're getting.

If you need your code to run in an ES5 environment, you need to include a Map polyfill (since Map didn't exist in ES5) that is written to be compatible with an ES5 environment so that Map can be called via .call as above. And if your code is running in a modern(ish) environment that already has Map, you'll still need to include the polyfill because of the way it gets called.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.