Edit: Turns out there was a bug related to this warning, fixed in Angular CLI 16.0.4. For Angular CLI 15 - 16.0.3 make sure you set target="ES2022"
to avoid the mismatch described below. Check your CLI version with ng version
.
Be careful not to misinterpret the warning, and its consequences!
The full message (as of Angular 16) says this:
TypeScript compiler options "target" and "useDefineForClassFields" are set to "ES2022" and "false" respectively by the Angular CLI. To control ECMA version and features use the Browerslist configuration. For more information, see https://angular.io/guide/build#configuring-browser-compatibility
NOTE: You can set the "target" to "ES2022" in the project's tsconfig to remove this warning.
One quite reasonable interpretation of this might be:
Angular is IGNORING whatever I put for compilerOptions.target
in your tsconfig.json
, and is compiling my code as ES2022.
However, that is NOT what is happening!
To confirm, I created a simple ng new
project with Angular 16 and updated my target to ES2015:
compilerOptions: {
"target": "ES2015"
}
I wrote the following lines of code in my AppComponent, using the nullish coalescing operator which is an ES2022 feature.
const cat = null;
const dog = { catName: 'Kim' };
const animal = cat ?? dog;
Looking at the .js compiled code (not the sourcemapped .ts file) running in the browser via ng serve
you'll see the following - demonstrating that the ??
has already been transpiled to be compatible with older browsers:
const animal = cat !== null && cat !== void 0 ? cat : dog;
This of course doesn't happen out-of-the-box with the ES2022 target.
So let's say you really need to support Safari 13.0 (which doesn't support ??) and think that everything is fine.
Wrong again!
Search in the browser for ??
and you'll see numerous places where ??
is used in the vendor.js file. It is NOT being transpiled there and therefore your app won't work on Safari 13.0.
That's where the browserslist comes in, which if configured will transpile the entire application for a certain target.
What the message really means in practice:
Your application code is being compiled for a target older than ES2022, which may lead to a mismatch between your code and vendor code. We recommend setting your target to ES2022 and using exclusively browserslist to control transpilation for older browsers, to ensure all code is transpiled as intended.
Why I am still confused:
The following commit which introduced this feature appears to set the target to ES2022 but it never actually takes effect for application code. Not sure why.
https://github.com/angular/angular-cli/pull/23936/commits/cdac700b93d5593ce92b44b1691941673eaf25b0#diff-2d55449c69797885b38f6b957a1fd03d27beda366a9270293719ec041cf15d0f