【问题标题】:Is TypeScript really a superset of JavaScript?TypeScript 真的是 JavaScript 的超集吗?
【发布时间】:2015-07-07 05:44:20
【问题描述】:

我刚开始使用 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 开发过程中发生了变化,还是我必须通过特定的编译器设置才能使其工作?

【问题讨论】:

  • 它是一个超集。但这并不意味着它可以 1) 编译和 2) 用作常规 JavaScript。 Objective-C 是 C/++ 的超集,但它有自己的编译器/IDE/环境。您必须遵循 TypeScript 指令,而不是将其与 JavaScript 进行逐字比较。
  • 嗯,也许这只是用词不当。这不是真正的 error 是吗?更多警告,因为它确实生成有效的Javascript。当然,TypeScript 经常吹捧为编译器提供 Javascript 应该“正常工作”
  • @RGraham 好了,所以语言在语法上兼容就好了。
  • error TS2094: The property 'bar' does not exist on value of type '{}'. 实际上是 tsc 的响应。但这不是一个错误,如果是,它肯定不是一个关键的错误:) 不过是个好问题。 TypeScript 乍一看总是很简单,但它的怪癖和 JS 一样多
  • 当我读到“错误 TS2094”时,在我的世界里这是一个 错误 ...这意味着 TypeScript 无效,即使编译器可能会发出工作JavaScript ...

标签: javascript compiler-errors typescript1.4


【解决方案1】:

定义

“所有 JavaScript 代码都是 TypeScript 代码,复制粘贴即可”

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

所以它有点像 JavaScript 之上的层。因此,当然底层层 (JavaScript) 可以通过层传递到顶部 (TypeScript),但不能反过来。

为什么不呢?

将其视为自行车 (JavaScript) 和摩托车 (TypeScript)。基本原理是相同的(两个轮子,一个车架),但摩托车作为发动机和一些增强功能。

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

编辑:

如果你的编译器抛出一个警告,为什么它会让 陈述错误?它只是说:嘿,你正在使用 TypeScript,它是 比你给我的更严格。

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

【讨论】:

  • 如果你可以将任何 JS 代码传递给 TypeScript 编译器,为什么有效的 JavaScript (var foo={}; foo.bar = 42;) 会抛出错误/警告?
  • @gruberb 但关键是它没有。看到 OP 给出了有效的 JS,它抛出了一个错误——我第一次也错过了这个
  • 给出了一个明确的例子,其中有效的 JS 代码不是有效的 TS 代码。如果你认为这是真的,你应该解释更多,而不是谈论摩托车和其他方式。
  • 如果 TypeScript 编译器抛出错误,我认为代码不是 valid TypeScript,即使编译器可能仍会发出有效的 JavaScript。如果“超集”的定义是任何 valid JavaScript 也是 valid TypeScript,那么 TypeScript不是 JavaScript 的超集。跨度>
  • “因此,您可以将摩托车 (TypeScript) 用作自行车 (JavaScript),但不能将自行车用作摩托车。”这完全是倒退。除非您有带...踏板的摩托车,否则您不能将摩托车用作自行车?你可以把马达装在自行车上;它们被称为轻便摩托车,它们很摇滚。就像 JS 一样,它很难摇滚。
【解决方案2】:

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

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

【讨论】:

  • 你用语言表达了我的感受,但我真的找不到合适的词来形容。 TypeScript 代码会编译并生成 JavaScript 输出
  • 如果 TypeScript 编译器抛出错误,我认为代码不是有效的 TypeScript,即使编译器可能仍会发出有效的 JavaScript。因此,我认为从技术上讲,TypeScript不是 JavaScript 的超集。这绝不会降低 TypeScript 的价值,因为这正是 TypeScript 的目标:约束 JavaScript 的“动态”部分。
  • @jbandi:是的,这正是问题所在。你不能只是复制 JavaScript 并重命名为 TypeScript,然后添加类型。你通常需要解决很多问题。还有一些有效的 JavaScript 表达式,在 TypeScript 中是不可能产生的,例如在箭头函数中访问原始 this 上下文。或者访问没有“this”的实例变量。因此,TypeScript 在技术上既是 javascript 的超级子集,又是 javascript 的子集。可以这么说,是一个子集。它们有很多交集,但 JavaScript 并不完全包含在 TypeScript 中。这就是问题所在。
  • @deceze 考虑到语言的 syntactic 有效性并不常见,而且可能不是 OP 想要的。如果是这种情况,那么int x = "hello world"; 将是有效的 C,因为它可以正确解析并且只有一个类型错误。当 TS 编译器发出错误并仍在编译代码时,编译不会“成功”并且生成的代码可能无法按预期运行。即使您接受此定义,TS 也不是答案中所述的 JS 的子集;它是一个超集(有有效的 TS 不是有效的 JS)。
  • 如果你不能在 TS 中编译相同的代码,你是否认为它仍然是一个“超集”对任何人都无关紧要。人们告诉我所有的 JS 代码都在 TypeScript 中工作,我可以复制粘贴它,这是错误的。这实际上很重要,因为复制粘贴代码很好。无论如何,是的,大多数人会期望“超集”意味着所有 JS 代码都在 TS 中编译。
【解决方案3】:

定理: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;

TS documentation 笔记

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

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

  1. 编译器似乎使用了传统意义上的术语warning,所以我们也应该从传统意义上解释error:错误表示编译失败。
  2. 文档表明生成的 JavaScript 不一定正确。不正确的输出似乎与没有输出一样糟糕(如果不比不上)。他们都应该被认为是失败的。
  3. TypeScript 编译器以非零状态码退出,这通常表明进程以某种方式失败。
  4. 如果我们将任何输出 JavaScript 的 TypeScript 程序称为“有效”,那么我们必须将以下 TypeScript 程序称为有效,因为它在发出错误后将一个点编译为空字符串:
.

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

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

【讨论】:

  • 我认为,如果 typescript 编译器发出的 Javascript 与输入 Javascript 的意图和功能相匹配,它就会成功。如果 TS 不是 JS 的超集,就会有有效的 JS 程序在 TS 编译后不再像以前那样运行。
  • 这个!如果 Typescript 是 Javascript 的超集,那么根据定义,所有有效的 Javascript 程序也都是有效的 Typescript 程序。这是对“超集”一词的误用。
【解决方案4】:

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

// 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 中导致了两种完全不同的解释,因此是该问题的反例。

【讨论】:

    猜你喜欢
    • 2015-11-28
    • 2022-11-12
    • 1970-01-01
    • 1970-01-01
    • 2012-07-16
    • 1970-01-01
    • 1970-01-01
    • 2010-09-15
    • 1970-01-01
    相关资源
    最近更新 更多