Angular项目如何绕过tsc转译检测浏览器optional chaining支持
问题描述
在Angular应用中,需要检测客户端浏览器对optional chaining(ES2020特性)的原生支持情况,从而决定加载库的现代ES版本还是legacy兼容版本。
目前遇到的问题是:Angular编译器(本质是tsc的通用行为)会将所有代码转译为配置的目标ES版本(当前配置为ES6),导致用来检测optional chaining支持的代码被转译,无法在运行时正常完成检测:
export function isOpChainingSupported(): boolean { const opChainingChecker = { support: true }; try { // 转译前代码: // return opChainingChecker?.support; // // 转译后变为 return opChainingChecker === null || opChainingChecker === void 0 ? void 0 : opChainingChecker.support; } catch { return false; } }
尝试将这段检测代码放到普通JS文件中,开启TS配置的allowJs来无报错导入,但没有效果:tsc仍然会将该文件代码转译。
目前想到三个不太满意的解决方案:
- 使用
eval('constObj?.prop')实现,但多数资料表示该方案存在安全风险; - 将存放检测代码的普通JS文件作为静态资源,动态加载执行;
- 单独为该检测函数封装一个ES工具库(目前的备选方案,但对于该需求来说过于冗余)。
请问有没有遗漏的更简单的实现方案?
解决方案
方案1:使用Function构造函数(推荐)
Function构造函数接收的字符串形式的代码不会被tsc转译,且相比eval安全很多——它的运行作用域为全局作用域,不会访问当前闭包的变量,只要代码字符串是固定的静态内容,完全不存在安全风险:
export function isOpChainingSupported(): boolean { try { const checker = new Function('return { support: true }?.support === true'); return checker(); } catch { return false; } }
该方案代码简洁,不需要额外资源或配置,满足需求。
方案2:在index.html中内联检测代码
把检测逻辑直接写在index.html的内联script标签中,挂载到全局window对象上,tsc完全不会处理这段代码:
- 在index.html的head标签中添加:
<script> window.__OP_CHAINING_SUPPORTED__ = (function() { try { return { support: true }?.support === true; } catch { return false; } })(); </script>
- 在TS代码中添加全局类型声明,直接读取全局变量即可:
declare global { interface Window { __OP_CHAINING_SUPPORTED__: boolean; } } export function isOpChainingSupported(): boolean { return window.__OP_CHAINING_SUPPORTED__; }
该方案性能更好,页面加载阶段就完成了检测,运行时直接读取结果即可。
内容的提问来源于stack exchange,提问作者Lincoln Alves
相关产品推荐
相关产品推荐

