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?
The target setting changes which JS features are downleveled and which are left intact. For example, an arrow function () => this will be turned into an equivalent function expression if target is ES5 or lower. Changing target also changes the default value of lib .
target. ES6 provides a metaproperty named new. target that allows you to detect whether a function or constructor was called using the new operator.
By default, the target is es2017 , which is supported in modern browsers.
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!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With