TypeScript真的是JavaScript的超集吗?

时间:2015-04-28 11:34:01

标签: javascript compiler-errors typescript1.4

我刚开始使用TypeScript,有时会遇到编译器错误“使用未声明的变量”。例如,以下工作在纯JavaScript中:

var foo = {};
foo.bar = 42;

如果我尝试在TypeScript中执行相同的操作,它将无法正常工作并向我提供上述错误。我必须这样写:

var foo :any = {};
foo.bar = 42;

在纯JavaScript中,带有any的类型定义既不是必需的也不是有效的,但在TypeScript中,这似乎是强制性的。我理解错误及其原因,但我总是在视频中听到并阅读文档:

typescriptlang.org

  

“TypeScript是JavaScript [...]”

的类型超集

Introduction Video @minute 3:20

  

“所有JavaScript代码都是TypeScript代码,只需复制并粘贴”

这是在TypeScript开发过程中发生了变化的事情,还是必须传递特定的编译器设置才能使其工作?

4 个答案:

答案 0 :(得分:19)

TypeScript存在的原因是有一个编译器和语言可以比vanilla Javascript更好地强制执行类型。任何常规Javascript都是有效的TypeScript,语法。这并不意味着编译器必须完全满意它。 Vanilla Javascript通常包含在类型安全性方面存在问题的代码。这并不能使无效的 TypeScript代码,但它正是TypeScript存在的原因,而且正是编译器指出这些问题的工作给你。

语言本身仍然是彼此的子/超集。

答案 1 :(得分:3)

定理:TypeScript既不是JavaScript的子集也不是其超集。

证明:

当我们说语言A是语言B的子集时,意味着所有有效的A程序也是有效的B程序。

这是有效的TypeScript程序,而不是有效的JavaScript程序:

let x: number = 3;

您标识了不是有效的TypeScript程序的有效JavaScript程序:

var foo = {};
foo.bar = 42;

复杂因素1:TypeScript几乎是一个超集。 TypeScript旨在成为JavaScript的近超集。最有效的JS也是有效的TS。通常,可以轻松地调整JS所没有的JS,而不会在TS中出错。

复杂因素2:非致命错误即使存在错误,TypeScript编译器有时也会生成您想要的JavaScript代码。我之前引用的您的示例发出了此错误

error TS2339: Property 'bar' does not exist on type '{}'.

也是这个JS代码

var foo = {};
foo.bar = 42;

TS documentation笔记

  

即使代码中有错误,也可以使用TypeScript。但是在这种情况下,TypeScript警告您的代码可能无法按预期运行。

我认为我们可以将其称为失败的编译(因此是无效的TypeScript),原因如下:

  1. 编译器似乎在常规意义上使用术语warning,因此我们也应该在常规意义上解释error:错误表示编译失败。
  2. 生成的代码无法按预期运行。它可以做一些完全不同的事情。想象一下两种语言A和B,其中在A中编译的任何字符串都在B中编译,但其功能却完全不同。我不会说A是B的子集,即使在语法上也是如此。
  3. 文档表明,所生成的JavaScript在意图上不正确。错误的输出似乎和没有输出一样糟糕(甚至比没有输出差)。它们都应该被视为失败。
  4. TypeScript编译器以状态码2退出,该状态码通常表示该进程以某种方式失败。
  5. 如果我们将任何输出JavaScript的TypeScript程序称为“有效”,那么我们将不得不调用以下TypeScript程序有效:

"

复杂因素3:TS接受JS文件: TypeScript编译器可以传递以.js结尾的文件(--allowJs请参见compiler documentation)。从这个意义上讲,TypeScript是JS的超集。所有.js文件都可以使用TypeScript进行编译。这可能不是问这个问题的人要问的意思。

我认为,复杂因素1是Anders Hejlsberg所追求的。这也可能证明TypeScript主页上的误导性行销是合理的。其他答案已成为复杂因素2的牺牲品。但是,其他答案中给出的一般建议是正确的:TypeScript是JavaScript之上的一层,旨在告诉您何时做不好的事情。它们是用于不同目的的不同工具。

答案 2 :(得分:2)

定义

  

“所有JavaScript代码都是TypeScript代码,只需复制并粘贴”

是真的。 因为任何JavaScript代码都可以传递给TypeScript编译器。

所以它是一种基于JavaScript的层。因此,当然底层Layer(JavaScript)可以通过层传递到顶层(TypeScript),但不是相反。

为什么不呢?

将其视为自行车(JavaScript)和摩托车(TypeScript)。基础是相同的(两个轮子,一个框架),但摩托车作为引擎和一些增强功能。

因此,您可以将摩托车(TypeScript)用作自行车(JavaScript),但不能将自行车用作摩托车。

编辑:

  

如果您的编译器发出警告,为什么它会发出警告   声明不对?它只是说:嘿,你正在使用TypeScript,它就是   比你给我的更严格。

See this example,它可以完美地编译JavaScript,但会发出警告。

答案 3 :(得分:1)

没有。在其他答案中,我相信技术原因已经得到很好的解释,但我注意到一个例子可能会立即与问题中的主张(不同的语义)相矛盾:

// In TypeScript
function f<A>(a: A) { return a; };

console.log(f<Function>(f)); // <-- This line. It will print the function f since it is an identify function that in this case takes self and returns self.

与下面的 JavaScript 示例比较

// In JavaScript
function f(a) { return a; };

console.log(f<Function>(f)); // <-- This line. This is VALID JavaScript

乍一看,您可能认为 JavaScript 示例存在语法错误。然而,一旦你仔细检查它,你会注意到实际上该行被执行为

console.log((f < Function) > f); // Evaluate to false

在 JavaScript 中完全有效。这实质上意味着同一行代码在 JavaScript 和 TypeScript 中导致了两种完全不同的解释,因此是该问题的反例。