TypeScript

127 阅读5分钟

「未完...」

一、TS核心语法

基础知识

TypeScript = JS + 静态类型校验(代码执行前能错误预警)

TS为JS的超集。

TS可以类型判断、类型推断

TS优势:

  1. 更容易帮我们发现程序中的问题
  2. 语法提示更加完善
  3. 语义更强,代码可读性更高

ts不能直接执行,需要编译成js才能执行

npm install typescript -g

安装之后,可以使用tsc将ts编译为js

安装ts-node可在node环境执行ts文件

npm i ts-node -g

ts-node demo.ts

ts-node 本身并不支持自动地监听文件变更然后重新执行,而这一能力又是某些项目场景下的刚需,如 NodeJs API 的开发。因此,我们需要 ts-node-dev 库来实现这一能力。ts-node-dev 基于 node-dev(你可以理解一个类似 nodemon 的库,提供监听文件重新执行的能力) 与 ts-node 实现,并在重启文件进程时共享同一个 TS 编译进程,避免了每次重启时需要重新实例化编译进程等操作。

首先,我们还是在全局安装:

npm i ts-node-dev -g

ts-node-dev 在全局提供了 tsnd 这一简写,你可以运行 tsnd 来检查安装情况。最常见的使用命令是这样的:

ts-node-dev --respawn --transpile-only app.ts

TS类型

常用的24种TS类型 (注意区分大小写)

1.基本类型:

number,string,boolean,symbol,null,undefined

2.根类型:

Object, {} (这两种数据类型一样,一个全写一个简写

根类型可接受除undefined和null之外的任意类型,Object只能赋给任意值, 不能调用方法,和any是不一样的

示例:

image.png

3.对象类型:

Array, object(注意大小写), function

示例:

image.png

4.枚举:

enum

  • 枚举的定义:用来存放一组固定的常量的序列

  • 枚举的分类:字符串枚举、数字枚举

    // 数字枚举
    // 可以不用给每个属性赋值
    enum Week {
      Monday = 1,
      Tuesday,
      Wensday,
      ThirsDay,
      Friday,
      Sarturday,
      Sunday
    }
    
    console.log(Week.Monday)
    console.log(Week["Monday"])
    
    console.log(Week[1])
    console.log(Week[5])
    
    //  字符串枚举
    enum WeekEnd {
        Monday = "Monday",
        Tuesday = "Tuesday",
        Wensday = "Wensday",
        ThirsDay = "ThirsDay",
        Friday = "Friday",
        Sarturday = "Sarturday",
        Sunday = "Sunday"
      }
      
      console.log(WeekEnd.Monday)
      console.log(WeekEnd["Monday"])
    
    /** 打印结果
    1
    1
    Monday
    Friday
    Monday
    Monday
    **/
    
  • 为什么要使用枚举类型?

    解决多次if / switch判断中值的语义化的问题

    1. 常量解决

    2. 使用常量带来的局限性

      方法参数不能定义为具体类型,只能初级使用number,string基本类型代替,降低了代码的可读性和可维护性

  • 使用枚举的好处

    1. 有默认值和可以自增值,节省编码时间
    2. 语义更清晰,可读性增强

    因为枚举是一种值类型的数据类型,方法参数可以明确参数类型为枚举类型

5.其他特殊类型:

any,unknown,never,void,元组 ( tuple),可变元组

  • never类型是为了避免出现未来扩展新的类没有对应类型的实现,目的是写出类型绝对安全的代码

    // never类型  
    // dataFlowAnalysisWithNever 方法穷尽了 DataFlow 的所有可能类型。  
    // 使用 never 避免出现未来扩展新的类没有对应类型的实现。,具的就是写出类型绝对安全的  
    type DataFlow = string | number  
    function dataFlowAnalysisWithNever(dataFlow: DataFlow) {  
        if (typeof dataFlow === "string") {  
            console.log("字符串类型:", dataFlow.length);  
        } else if (typeof dataFlow === "number") {  
            console.log("数值类型:", dataFlow.toFixed(2));  
        } else {  
            let data = dataFlow  
        }  
    }  
    
    dataFlowAnalysisWithNever("string")  
    dataFlowAnalysisWithNever(3.199923)
    
  • any, unknown的两点区别和应用场景

    any 和 unknown 在开发中和第三方包源码底层经常看到,弄清楚它们的区别很重要。

    相同: any 和unknown 可以是任何类的父类,所以任何类型的变量都可以赋值给 any 类型或unknown类型的变量。

    不同点1: any 也可以是任何类的子类,但 unknown 不可以,所以 any 类型的变量都可以赋值给其他类型的变量

    不同点2: 不能拿 unknown 类型的变量来获取任何属性和方法,但 any 类型的变量可以获取任意名称的属性和任意名称的方法

    any 比较典型的应用场景: 1.自定义守卫 2.需要进行 as any 类型断言的场景

    // Vue3 源码 片段
    // any 的应用场景--自定义守卫中使用 any
    export function isRef(r: any): r is Ref f
    return Boolean(r && r.__v_isRef true) // any类型的 r 参数在雨数内部获取属性
    

    unknown 一般用作函数参数: 用来接受任意类型的变量实参,但在函数内部只用于再次传递或输出结果,不获取属性的场景 (使用unknown的场景都可以使用any来替代)

    // Vue3 源码 片段 ref 的 unknown 参数
    function ref(value?: unknown) {
        return createRef(value) // 函数内部只用于再次传递值,不获取属性
    }
    

6.合成类型:

联合类型(Union),交叉类型

// 联合类型  
let str: string | number = 3  
console.log("str:", str)  
  
// 交叉类型  
type Obj1 = { username: string }  
type Obj2 = { age: number }  
let obj1: Obj1 = { username: "abc" }  
let obj2: Obj2 = { age: 25 }  
  
let obj3: Obj1 & Obj2 = { username: "kaka", age: 25 }

7.字面量数据类型:

image.png

接口和应用场景

接口: 另一种定义对象类型的类型

接口应用场景:

(1)一些第三方包或者框架底层源码中有大量的接口类型

(2)提供方法的对象类型的参数时使用

(3)为多个同类别的类提供统一的方法和属性声明

如何定义接口

继承接口

新的接口只是在原来接口继承之上增加了一些属性或方法,这时就用接口继承