12

I have the following settings in thetsconfig.json. I added "es2017" to use Array.includes.:

{
  "compilerOptions": {
    "lib": [
      "es6",
      "es2017",
      "dom"
    ],
    "module": "es6",
    "target": "es5"
  }
}

Now, I realized, that I have to add import 'core-js/es7/array'; to the polyfills.ts, to use Array.includes also for the Internet Explorer 11. The target in the tsconfig.json is set to es5, which does not have Array.includes.

Why do I need to add the polyfill?

BuZZ-dEE
  • 6,075
  • 12
  • 66
  • 96
  • "The target in the tsconfig.json is set to es5, which does not have Array.includes". Aren't you answering to the question yourself ? –  May 23 '19 at 13:28
  • No, I thought, if I have `"es2017"` in `lib`, I can use `"es2017"` features, that are transpiled to the target `"es5"`. Because `Array.includes` is not in `"es5"`, it is transpiled to `Array.indexOf => 0` or something else. – BuZZ-dEE May 23 '19 at 13:32
  • yes but you said it yourself, you're targeting ES5. This means you need the polyfills to make it work. The compiler doesn't know polyfills out of the box, you have to import them so that it can import it. At least that's what I understood ... –  May 23 '19 at 13:34
  • Why I don't need the polyfill in Firefox or Chrome? If the `target` is set to `es5`, what does the Typescript transpiler then generate, because `Array.includes` is not in `es5`? – BuZZ-dEE May 23 '19 at 14:14
  • It generates it with the polyfill ! –  May 23 '19 at 14:43
  • Possible duplicate of [Using latest JavaScript features in TypeScript, such as ES2018](https://stackoverflow.com/questions/51043439/using-latest-javascript-features-in-typescript-such-as-es2018/51044240#51044240) – jcalz May 23 '19 at 14:58
  • You don't need the polyfill in Firefox or Chrome because their runtimes have the method in question. They are just running whatever version of ECMAScript they support; they don't have any reason to throw a runtime error when given `[1,2,3].includes(0)`, since the browsers don't even know about the "target" version of your TypeScript code. – jcalz May 23 '19 at 15:34

1 Answers1

14

TypeScript does not auto-polyfill code (see microsoft/TypeScript#3101). The "official" reason from the relevant GitHub issue seems to be, as @RyanCavanaugh said:

Having the compiler try to figure out which [ES20XX] methods you need, and where to emit them, and when, with controls for people who don't want the polyfills emitted, and ways to change where those polyfills come from, etc, is a big mess that isn't justified by the potential gains over simply including a normal [ES20XX] polyfill library in your script context.

And, as it's mentioned in that issue, emitting runtime code is a non-goal of TypeScript:

[Non-Goal #]6. Provide additional runtime functionality or libraries. Instead, use TypeScript to describe existing libraries.


I'm guessing that some of the confusion comes from the fact that TypeScript does downlevel some language features when targeting earlier EcmaScript versions. The main criterion used when determining if a feature will be emitted as downleveled code or whether it needs a polyfill is syntax:

If the new language feature is syntactically invalid in the targeted version, then it will either be downleveled or you will get a compile time warning. You can't polyfill invalid syntax. For example, class Foo {} is not and cannot be valid ES5 code... so it will be converted into a constructor function instead when targeting ES5.

If, on the other hand, the language feature is syntactically valid in the targeted version, it will be emitted as-is with no warning. So [1,2,3].includes(0) is perfectly valid ES5 code in terms of syntax. Assuming that someone adds an Array.prototype.includes method to an ES5 engine, it will even work at runtime. So it is emitted as-is. Note that when you include es2017 in your lib compiler options, you're telling TypeScript that the runtime will support ES2017 typings, and so there is no compile-time warning. Adding typing libraries does not do anything to the runtime itself... so you're responsible for polyfilling/shimming anything you need. From the compiler's perspective it can't deal with the situation where you lied to it about what methods exist at runtime. Obviously that's not much consolation for someone frustrated by a runtime error, though.

Oh well, it is what it is, I guess.


Hope that helps. Good luck!

jcalz
  • 264,269
  • 27
  • 359
  • 360
  • How can you scan your own code to know which polyfill libraries you need? :D – mesqueeb Jul 28 '20 at 23:34
  • @mesqueeb A few months late, but setting the `lib` compiler option correctly will get you errors for any methods you try to use that aren’t present in the version targeted by the indicated libraries. So that would be a way to figure out what you need to polyfill: set your `lib` to the lowest available version, note what errors spring up, and polyfill those. – KRyan Oct 10 '20 at 21:04