V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
wjx0912
V2EX  ›  JavaScript

typescript 类型转换请教

  •  
  •   wjx0912 · 2022-08-01 22:47:41 +08:00 · 2280 次点击
    这是一个创建于 850 天前的主题,其中的信息可能已经有所发展或是发生改变。
    var str = '1'
    var str2:number = <number> <any> str
    console.log(typeof str2) // 问题 1:为什么输出 string
    str2 = 1
    console.log(typeof str2)
    str2 = '3' // 问题 2:为什么编译错误

    ts 在编译的时候是怎么控制类型的呢
    谢谢
    9 条回复    2022-08-02 09:09:00 +08:00
    wjx0912
        1
    wjx0912  
    OP
       2022-08-01 22:50:39 +08:00
    再追加几行:
    var str3:number = <number> <any> str
    var num4: number = 3 + str3
    console.log(num4, typeof num4) // 输出: 31 string

    大佬指点下编译器行为。谢谢了
    noe132
        2
    noe132  
       2022-08-01 23:15:45 +08:00   ❤️ 1
    和 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 个都转为字符,然后再进行字符串拼接的操作。
    noe132
        3
    noe132  
       2022-08-01 23:19:34 +08:00
    当你需要把 string 内的值转换成 number 类型时,需要使用 parseInt / parseFloat / Number 这样的方法来处理。当 string 内的字符无法被解析成 number 时,通常都会给一个特殊值 NaN (Not a Number),这个值不和任何值相等,甚至 NaN 也不等于 NaN ,判断一个值是不是 NaN 的方法是 Number.isNaN
    Trim21
        4
    Trim21  
       2022-08-01 23:23:54 +08:00 via Android
    typeof 是运行时的变量类型,真正的 js 运行时并不知道你用 ts 指定的变量类型

    后面那个报错是 ts 编译器的报错,实际上是可以忽略然后强行编译成 js ,并且正常运行的。
    thinkershare
        5
    thinkershare  
       2022-08-01 23:55:00 +08:00
    问题 1:为什么输出 string, 因为 typescript 只有编译时行为, 没有运行时行为,强制类型转换就是告诉编译器你知道的比它多, 让它信任你变量是你知道的类型, 但这并不会改变变量值的实际类型
    问题 2: 为什么是编译错误, 因为 typescript 核心作用就是做类型检测和提供智能提示, 这里变量的类型是 number, 当然不应该分配一个字符串给它, 因为 number 和 string 不相容
    你可以理解为 TypeScript 绝对不会修改 JavaScript 的运行时行为, 它本质上是个 Type Annotation System.
    Aloento
        6
    Aloento  
       2022-08-02 02:28:55 +08:00   ❤️ 1
    ts...编译后就没有类型了
    wjx0912
        7
    wjx0912  
    OP
       2022-08-02 09:08:08 +08:00
    @noe132 感谢。回答的太仔细了~
    wjx0912
        8
    wjx0912  
    OP
       2022-08-02 09:08:29 +08:00
    @Trim21 @Aloento 谢谢
    wjx0912
        9
    wjx0912  
    OP
       2022-08-02 09:09:00 +08:00
    @thinkershare 这个解释的很清楚。谢谢了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2852 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 12:33 · PVG 20:33 · LAX 04:33 · JFK 07:33
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.