我刚开始使用TypeScript,有时会遇到编译器错误“使用未声明的变量”。例如,以下工作在纯JavaScript中:
var foo = {};
foo.bar = 42;
如果我尝试在TypeScript中执行相同的操作,它将无法正常工作并向我提供上述错误。我必须这样写:
var foo :any = {};
foo.bar = 42;
在纯JavaScript中,带有any的类型定义既不是必需的也不是有效的,但在TypeScript中,这似乎是强制性的。我理解错误及其原因,但我总是在视频中听到并阅读文档:
“TypeScript是JavaScript [...]”
的类型超集
Introduction Video @minute 3:20:
“所有JavaScript代码都是TypeScript代码,只需复制并粘贴”
这是在TypeScript开发过程中发生了变化的事情,还是必须传递特定的编译器设置才能使其工作?
答案 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;
即使代码中有错误,也可以使用TypeScript。但是在这种情况下,TypeScript警告您的代码可能无法按预期运行。
我认为我们可以将其称为失败的编译(因此是无效的TypeScript),原因如下:
warning
,因此我们也应该在常规意义上解释error
:错误表示编译失败。 "
复杂因素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 中导致了两种完全不同的解释,因此是该问题的反例。