Inconsistent behavior when filtering out redundant inner-block variable assignment
Hi, I think I found a small edge-case bug in Terser (v5.51.2) with unsafe enabled. I am using Typescript and had some code blocks where I was using variable assignment to narrow down types, expecting Terser to filter that code out at runtime, as in JS it is basically redundant, assigning a const to another const. (It can't ever be something weird like a property accessor, afaik, since it is a direct assignment) But I found out that in some cases, Terser correctly filters these out, but in other cases, it doesn't.
Example of what I'm doing:
function someMethod(input: DataType) {
const data: WiderType = input.data;
if(someRuntimeCondition) {
const knownData = data as NarrowType; //Terser unsafe should vaporize this code from the mortal realm, but sometimes doesn't?
doStuff(knownData.propA);
doStuff(knownData.propB);
//Etc...
}
}But of course to make sure TSC is not just doing weird stuff that's confusing Terser, I decided to make a minimum reproducible example in pure JS. Here is the most simple example I could force it to not filter the line out in:
function test(val) {
const data = val.data;
function subFunc() {
const d = data;
console.log(d.a, d.b);
}
return subFunc;
}Terserized w/ compress: {unsafe: true}
function test(n){const t=n.data;return function(){const n=t;console.log(n.a,n.b)}}But change some tiny thing like this and suddenly, it works:
function test(val) {
const data = val.data;
function subFunc() {
const d = data;
console.log(d.a);
}
return subFunc;
}Terserized:
function test(n){const t=n.data;return function(){console.log(t.a)}}I also tested with all of the other extra unsafe options enabled too just to check, and it still doesn't filter this out btw.
Source: terser/terser