和 C / Java 等语言很大不同的是,ts 的编译时类型和运行时类型是完全分开的,而且 ts 的编译相对来说非常简单,只需要去掉所有类型标注就是编译几乎全过程。any 这个类型可以看作一种 opt-out ,当你不像让 ts 做检查的时候就可以用 any 。而很多其他静态类型的语言根本就不存在这样的概念,这也是因为 ts 编译的 target 是 js ,是一个动态类型的语言。
ts 的编译和 C / Java 这类语言的编译有很大的区别,ts 的编译过程可以简单看做 2 步,1 对类型做检查,2 去掉所有类型标注。
现在回答一下你的问题
1. 因为 typeof 是一个运行时执行的操作符,会根据运行时变量的类型输出结果。ts 中的类型也有 typeof 操作符,比如
const a = 1
type A = typeof a
这里的 typeof 是编译时的,得到的结果是一个 ts 的类型,和你的例子中的 typeof 虽然长得一模一样,但却是 2 个不一样的东西。
2. str2 的类型是 number ,赋值一个 '3' 相当于赋值一个 string 给 number ,当然是不允许的。
3. 即使你用 as any as number 把一个 string 类型的值赋值给了一个 number 类型的变量,但是在运行时这个变量实际持有的还是 string 。ts 的类型转换不会对值做任何操作,而只是影响类型检查的结果。所以在运行时,3 + str3 实际上是 3 + '1' ,得到的结果则是 '31'。至于为啥 结果是 '31',这属于动态类型语言的问题,具体的行为得看规范(
https://262.ecma-international.org/5.1/#sec-11.6.1 ),但简单来说就是如果出现了 数字+字符 的情况,无论左侧是字符还是右侧是字符,会先把 2 个都转为字符,然后再进行字符串拼接的操作。