我经常听到人们发表这样的陈述
所有JavaScript代码都是合法的TypeScript代码
要么
TypeScript是JavaScript的超集
但是当我写出一些完全合法且合理的 JS代码时,它们具有完全确定性的行为:
var x = "hello".substr("w").toStrig * { m: 3 / true } + window + parseInt(Element).fzq;
ECMAScript定义x
应该具有"NaN[object Window]undefined"
看起来完全正常的值,但是我从TypeScript得到了一堆错误!是不是这句话"所有JS都是TS"的谎言呢?这是怎么回事?
所有JavaScript代码都是合法的TypeScript代码
这是这意味着什么:
TypeScript不会更改现有JavaScript 的语法
TypeScript不会更改现有JavaScript 的行为
TypeScript 确实认为某些JS代码有类型警告,因为这就是重点
TypeScript将成功解析所有合法的JavaScript代码.它将按原样发出此代码(减去下行,例如,如果您的目标是ES5或更低,ES6箭头函数将转换为等效的ES5代码).如果您愿意,可以忽略此JS代码生成的类型警告; 类型警告不会阻止TypeScript写入输出.js文件.
TypeScript不会改变现有JavaScript代码的行为,即使很多人都希望它能做到!任何通过编译器运行的JS代码都会像直接运行*一样运行.
TypeScript 可能会对其认为不正确的代码发出类型警告.
错误是什么意思?请注意,JavaScript是确定性的.例如,与C++不同,基本上不可能导致"实现定义"的行为.JavaScript也很少抛出异常; 与其他语言不同,它可能在尝试通过函数乘以对象时引发异常,JS产生NaN
.通过拼写错误的名称访问属性将产生undefined
而不是运行时错误(很多人都很懊恼).所以这里的"错误"栏是故意设置的,比"崩溃你的计算机"或"抛出异常"更严格.
例如,像这样的一些代码都是合法的 JavaScript,甚至不会抛出异常.TypeScript认为这些行中的每一行都有错误; 这通常被使用者认为是积极的:
var x = { } + 3; // Error, can't add objects and numbers var y = "hello world".substr(1, 2, 3, 4, 5); // Error, too many parameters var z = { x: 1, x: 2 }; // Error, duplicate property 'x' var q = x[z]; // Error, indexing by an object doesn't really work... var u = "hi".lenth; // Error, no property 'lenth' on string
一个共同的反驳是这样的
"ECMAScript规范定义了将
Math.max
其参数强制转换为数字,因此调用Math.max(someString, someOtherString)
" 应该是合法的"
确实,ECMAScript规范明确定义了在运行时发生的强制.但是,这种逻辑并没有给我们任何实际的见解.从表面上看,这个逻辑表明,因为所有参数都在运行时被强制转换为数字,所以写入应该是合法的
var x = Math.max("hello", window.setTimeout, { });
毕竟,这段代码确实有定义的行为!但是这就错过了森林的树木 - 这个代码对于"正确"的任何合理定义都是正确的,这显然是不可信的.TypeScript的存在是基于一些JavaScript代码不正确并且您想知道它的概念.
规范描述发生的事实对于您是否正在编写正确的程序没有指导意义.如果你吃岩石,医生可以清楚地描述你会发生什么,但这并不意味着岩石就是食物.
查看ECMAScript规范是一个类别错误,该规范旨在指定行为,并确定它实际上是描述正确代码的规范性文档.如果你愿意,你可以运用虚无主义理论"规范所定义的任何东西都可以",并使用TypeScript的变体,它永远不会发出类型警告.此变体广泛可用,称为"JavaScript".
*
:此规则的例外情况是由于运行时的限制而可能存在可检测差异的向下级别,例如堆栈跟踪可能不同