TypeScript 真的是 JavaScript 的超集吗?
Is TypeScript really a superset of JavaScript?
我刚开始使用 TypeScript,有时会遇到编译器错误 "use of undeclared variable"。例如,以下内容在普通 JavaScript 中有效:
var foo = {};
foo.bar = 42;
如果我尝试在 TypeScript 中做同样的事情,它不会工作,并给我上面提到的错误。我必须这样写:
var foo :any = {};
foo.bar = 42;
在普通的 JavaScript 中,带有 any 的类型定义既不是必需的也不是有效的,但在 TypeScript 中这似乎是强制性的。我了解错误及其原因,但我总是在视频中听到并在文档中阅读:
"TypeScript is a typed superset of JavaScript [...]"
Introduction Video @minute 3:20:
"All JavaScript code is TypeScript code, simply copy and paste"
这是在 TypeScript 开发过程中发生的变化,还是我必须通过特定的编译器设置才能使其工作?
定义
"All JavaScript code is TypeScript code, simply copy and paste"
是真的。 因为任何 JavaScript 代码都可以传递给 TypeScript 编译器。
所以它有点像 JavaScript 之上的一层。因此,底层层 (JavaScript) 当然可以通过层传递到顶部 (TypeScript), 但反之则不行。
为什么不呢?
把它想象成一辆自行车 (JavaScript) 和一辆摩托车 (TypeScript)。基础是一样的(两个轮子,一个车架),但摩托车作为发动机和一些增强功能。
因此,您可以将摩托车 (TypeScript) 用作自行车 (JavaScript),但不能将自行车用作摩托车。
编辑:
If your compiler throws a warning, why does it make the
statement wrong? It just says: Hey, you are using TypeScript, and it's
more strict than what you gave me.
See this example,它可以完美地编译为 JavaScript,但会引发警告。
TypeScript 存在的原因是拥有一种编译器和语言,可以比 vanilla Javascript 更好地执行类型。任何常规 Javascript 都是有效的 TypeScript, 在语法上 。这并不意味着编译器必须对此完全满意。 Vanilla Javascript 通常包含在类型安全方面存在问题的代码。这并不会使它成为 无效的 TypeScript 代码,但这正是 TypeScript 存在的原因,并且向您指出这些问题正是编译器的工作。
语言本身仍然是彼此的sub/supersets。
定理: TypeScript 既不是 JavaScript.
的子集也不是超集
证明:
当我们说语言 A 是语言 B 的子集时,我们的意思是所有有效的 A 程序也是有效的 B 程序。
这是一个有效的 TypeScript 程序,它不是一个有效的 JavaScript 程序:
let x: number = 3;
您确定了一个有效的 JavaScript 程序,但它不是有效的 TypeScript 程序:
var foo = {};
foo.bar = 42;
复杂因素 1:TypeScript 几乎是一个超集。 TypeScript 旨在成为 JavaScript 的近乎超集。大多数有效的 JS 也是有效的 TS。 JS 不是的通常可以很容易地调整以在 TS 中编译而不会出错。换句话说,最有效的JS也是有效的TS。
复杂因素 2:非致命错误 即使存在错误,TypeScript 编译器有时也会生成您想要的 JavaScript 代码。我之前引用的您的示例发出此错误
error TS2339: Property 'bar' does not exist on type '{}'.
还有这个JS代码
var foo = {};
foo.bar = 42;
You can use TypeScript even if there are errors in your code. But in this case, TypeScript is warning that your code will likely not run as expected.
我认为我们可以将其称为编译失败(因此 TypeScript 无效),原因如下:
- 编译器似乎在常规意义上使用术语
warning
,所以我们也应该在常规意义上解释error
:错误表示编译失败。
- 文档表明生成的 JavaScript 不一定正确。不正确的输出看起来和没有输出一样糟糕(如果不是更糟的话)。他们都应该被认为是失败的。
- TypeScript 编译器以非零状态代码退出,这通常表示进程以某种方式失败。
- 如果我们调用任何输出 JavaScript“有效”的 TypeScript 程序,那么我们必须将以下 TypeScript 程序称为有效,因为它在发出错误后会编译为空字符串:
.
复杂因素 3:TS 接受 JS 文件: TypeScript 编译器可以传递以 .js
结尾的文件(参见 compiler documentation for --allowJs
).从这个意义上说,TypeScript 是 JS 的超集。所有 .js
文件都可以用 TypeScript 编译。这可能不是访问此问题的人要问的问题。
我认为使因素 1 复杂化是 Anders Hejlsberg 所要解决的问题。这也可能证明 TypeScript 主页上的误导性营销是合理的。其他答案已成为使因素 2 复杂化的牺牲品。但是其他答案中给出的一般建议是正确的:TypeScript 是 JavaScript 之上的一层,旨在告诉您何时做错事情。它们是用于不同目的的不同工具。
没有。在其他答案中,我相信技术原因已经得到很好的解释,但我注意到一个例子可以立即与问题中的声明相矛盾(不同的语义):
// 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 中产生了 2 种完全不同的解释,因此是问题的反例。
我刚开始使用 TypeScript,有时会遇到编译器错误 "use of undeclared variable"。例如,以下内容在普通 JavaScript 中有效:
var foo = {};
foo.bar = 42;
如果我尝试在 TypeScript 中做同样的事情,它不会工作,并给我上面提到的错误。我必须这样写:
var foo :any = {};
foo.bar = 42;
在普通的 JavaScript 中,带有 any 的类型定义既不是必需的也不是有效的,但在 TypeScript 中这似乎是强制性的。我了解错误及其原因,但我总是在视频中听到并在文档中阅读:
"TypeScript is a typed superset of JavaScript [...]"
Introduction Video @minute 3:20:
"All JavaScript code is TypeScript code, simply copy and paste"
这是在 TypeScript 开发过程中发生的变化,还是我必须通过特定的编译器设置才能使其工作?
定义
"All JavaScript code is TypeScript code, simply copy and paste"
是真的。 因为任何 JavaScript 代码都可以传递给 TypeScript 编译器。
所以它有点像 JavaScript 之上的一层。因此,底层层 (JavaScript) 当然可以通过层传递到顶部 (TypeScript), 但反之则不行。
为什么不呢?
把它想象成一辆自行车 (JavaScript) 和一辆摩托车 (TypeScript)。基础是一样的(两个轮子,一个车架),但摩托车作为发动机和一些增强功能。
因此,您可以将摩托车 (TypeScript) 用作自行车 (JavaScript),但不能将自行车用作摩托车。
编辑:
If your compiler throws a warning, why does it make the statement wrong? It just says: Hey, you are using TypeScript, and it's more strict than what you gave me.
See this example,它可以完美地编译为 JavaScript,但会引发警告。
TypeScript 存在的原因是拥有一种编译器和语言,可以比 vanilla Javascript 更好地执行类型。任何常规 Javascript 都是有效的 TypeScript, 在语法上 。这并不意味着编译器必须对此完全满意。 Vanilla Javascript 通常包含在类型安全方面存在问题的代码。这并不会使它成为 无效的 TypeScript 代码,但这正是 TypeScript 存在的原因,并且向您指出这些问题正是编译器的工作。
语言本身仍然是彼此的sub/supersets。
定理: TypeScript 既不是 JavaScript.
的子集也不是超集证明:
当我们说语言 A 是语言 B 的子集时,我们的意思是所有有效的 A 程序也是有效的 B 程序。
这是一个有效的 TypeScript 程序,它不是一个有效的 JavaScript 程序:
let x: number = 3;
您确定了一个有效的 JavaScript 程序,但它不是有效的 TypeScript 程序:
var foo = {};
foo.bar = 42;
复杂因素 1:TypeScript 几乎是一个超集。 TypeScript 旨在成为 JavaScript 的近乎超集。大多数有效的 JS 也是有效的 TS。 JS 不是的通常可以很容易地调整以在 TS 中编译而不会出错。换句话说,最有效的JS也是有效的TS。
复杂因素 2:非致命错误 即使存在错误,TypeScript 编译器有时也会生成您想要的 JavaScript 代码。我之前引用的您的示例发出此错误
error TS2339: Property 'bar' does not exist on type '{}'.
还有这个JS代码
var foo = {};
foo.bar = 42;
You can use TypeScript even if there are errors in your code. But in this case, TypeScript is warning that your code will likely not run as expected.
我认为我们可以将其称为编译失败(因此 TypeScript 无效),原因如下:
- 编译器似乎在常规意义上使用术语
warning
,所以我们也应该在常规意义上解释error
:错误表示编译失败。 - 文档表明生成的 JavaScript 不一定正确。不正确的输出看起来和没有输出一样糟糕(如果不是更糟的话)。他们都应该被认为是失败的。
- TypeScript 编译器以非零状态代码退出,这通常表示进程以某种方式失败。
- 如果我们调用任何输出 JavaScript“有效”的 TypeScript 程序,那么我们必须将以下 TypeScript 程序称为有效,因为它在发出错误后会编译为空字符串:
.
复杂因素 3:TS 接受 JS 文件: TypeScript 编译器可以传递以 .js
结尾的文件(参见 compiler documentation for --allowJs
).从这个意义上说,TypeScript 是 JS 的超集。所有 .js
文件都可以用 TypeScript 编译。这可能不是访问此问题的人要问的问题。
我认为使因素 1 复杂化是 Anders Hejlsberg 所要解决的问题。这也可能证明 TypeScript 主页上的误导性营销是合理的。其他答案已成为使因素 2 复杂化的牺牲品。但是其他答案中给出的一般建议是正确的:TypeScript 是 JavaScript 之上的一层,旨在告诉您何时做错事情。它们是用于不同目的的不同工具。
没有。在其他答案中,我相信技术原因已经得到很好的解释,但我注意到一个例子可以立即与问题中的声明相矛盾(不同的语义):
// 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 中产生了 2 种完全不同的解释,因此是问题的反例。