【问题标题】:With Closure Compiler what are the benefits of Array<T> annotation vs. just Array?使用 Closure Compiler,Array<T> 注释与仅 Array 相比有什么好处?
【发布时间】:2015-10-30 01:38:35
【问题描述】:

我希望 Closure Compiler 会在下面的所有行上发出警告,但只有 3) 显示为问题。 Type Checking Array Contents with Closure-Compiler 涉及到这一点,但我的问题是,鉴于这些限制,注释 Array&lt;T&gt;Array 有什么好处?我觉得这是一种虚假的安全感。

// ==ClosureCompiler==
// @compilation_level SIMPLE_OPTIMIZATIONS
// @output_file_name default.js
// @warning_level VERBOSE
// ==/ClosureCompiler==

/** @type {!Array<!string>} */
var xs = [];
xs.push(42);       // 1) no warning
xs.push(null);     // 2) no warning
xs = 'foo'         // 3) warns - found: string, required: Array<string>
xs = [1,2,3];      // 4) no warning

快速编辑:您可以在http://closure-compiler.appspot.com/ 使用此代码

【问题讨论】:

  • Javascript 没有类型限制。您可以var xs = true; 然后xs++; 除非其他解释器有限制,否则您将没有安全性....但是,如果您执行意外操作,大多数系统会通知您。据我所知,这是唯一的优势。

标签: javascript google-closure-compiler google-closure typechecking


【解决方案1】:

我怀疑这是因为externs definition for Array.prototype.push 不太正确。如果您删除 @this 类型,那么您应该得到预期的错误。不过,可能是由于某种原因添加了 {length: number} 部分,因此删除它可能会在某处破坏某些现有代码。

【讨论】:

  • 这是真的。 Array.prototype 方法是通用的,它们可以接受任何“类数组”对象(NodeList、TypedArray、Arguments 等)。但是,当 Array 实现 IArrayLike(我们在上一个版本中引入)时,这将得到修复。然后不是{length:number}|Array&lt;T&gt;,而是简单的IArrayLike&lt;T&gt;,它将按照我们的意愿工作。
  • @John 谢谢你。那么上面的xs = [1,2,3]; 案例呢? xs 是明确的 Array&lt;string&gt;[1,2,3] 似乎最坏的情况是被推断为 Array&lt;*&gt;。似乎应该发出警告?
  • 这有点不同,只是对象字面量被推断为“Array>”并且编译器中的“新类型推断”发生了变化。
【解决方案2】:

您将获得与其他静态语言一样的泛型优势。
假设您要创建一个字符串数组,然后使用它们的长度对它们进行排序。

var arr = [];    
arr.sort(function(a, b) { return a.length - b.length; });

如果您将数组注释为Array,那么您将能够向数组添加一个数字,并且闭包编译器不会抱怨。
最终你会遇到一个异常,因为数字没有长度属性。
如果您将数组注释为字符串数组Array&lt;string&gt;,那么您将确保长度属性存在并且没有人能够插入除字符串之外的任何其他类型。

我不明白为什么你用字符串没有编译错误,但如果你用数字试试,你会得到不同的编译结果。

// ==ClosureCompiler==
// @compilation_level SIMPLE_OPTIMIZATIONS
// @output_file_name default.js
// @warning_level VERBOSE
// ==/ClosureCompiler==

/** @type {!Array<!number>} */
var xs = [];
xs.push(42);
console.log(xs[0].length);

=> 
Number of warnings: 1

JSC_INEXISTENT_PROPERTY: Property length never defined on Number at line 4 character 18
console.log(xs[0].length);
              ^ 

【讨论】:

  • 在上面的示例中,我将 xs 注释为 Array&lt;string&gt; 并且能够将非字符串添加到数组中。 xs 保留 Array&lt;string&gt; 类型,但现在包含非字符串。我希望它按照你描述的方式工作:)
  • 你使用的是高级模式编译吗?
  • 我不在这个例子中,不。但它似乎不会影响类型检查,只会影响代码被缩小/转换的程度。 developers.google.com/closure/compiler/docs/compilation_levels
  • 我的印象是编译器发出警告但没有提供那种级别的类型安全(即确保没有添加不合格的类型)?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-08-13
  • 2012-06-05
  • 1970-01-01
  • 2020-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多