全局识别的元素、Typescript 和仅限 Safari 的错误?

Globally identified elements, Typescript, and Safari-only bug?

假设您有这样一个 select 元素:

<select id="Stooge" name="Stooge">
    <option value="0">Moe</option>
    <option value="1">Larry</option>
    <option value="2">Curly</option>
</select>

根据 spec,当浏览器解析此页面时,它会创建一个全局范围的 javascript 变量 window.Stooge。到目前为止一切顺利。

在我的 TypeScript 代码中,我想以强类型的方式引用选项,所以我有以下内容:

enum Stooge
{
  Moe,
  Larry,
  Curly
}

编译成 javascript 像这样:

var Stooge;
(function (Stooge) {
    Stooge[Stooge["Moe"] = 0] = "Moe";
    Stooge[Stooge["Larry"] = 1] = "Larry";
    Stooge[Stooge["Curly"] = 2] = "Curly";
 })(Stooge || (Stooge = {}));  <---error here

我的问题是:在每个浏览器中 除了 Safari,这工作正常。但是在 Safari 中,我收到以下错误:

YourFile.js:[Line X]TYPE_MISMATCH_ERR: DOM Exception 17: The type of an object was incompatible with the expected type of the parameter associated to the object.

这只会发生在枚举恰好与 DOM 元素同名的情况下,我想这是因为这两个定义之间存在冲突,除了相同的代码不会导致任何Safari 以外的错误。

那么,为什么它在其他浏览器中可以正常工作?有没有办法在 Safari 中解决这个问题? (我可以重命名枚举或 DOM 元素,但我想尽可能避免使用人工命名约定。)

您应该尽可能避免将任何内容放在全局范围内。外部模块(即将重命名为更简单的名称,模块)是执行此操作的好方法。使用外部模块,您的 enum 将安全地隐藏在模块的范围内,并且不应与其他任何内容发生冲突。

另一个解决方案是使用一个常量枚举,它被转换成普通数字(即枚举类型被擦除)。例如,以下 TypeScript:

const enum Stooge
{
  Moe,
  Larry,
  Curly
}

var x = Stooge.Curly;

结果如下JavaScript:

var x = 2 /* Curly */;

您最后的选择是避免可能冲突的名称。将某些东西放在全局范围内时,尽可能具体有助于将冲突风险降至最低。