• typescript核心


    变量后面约定类型的语法,就是类型注解

    作用: 约定类型,明确提示

    // 类型注解
    
    let age:number = 18;
    age = 19;
    // age = "hello";  //不能将类型“string”分配给类型“number”
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • :number 就是类型注解,为变量提供类型约束
    • 约定了什么类型,就只能给该变量赋值什么类型的值,否则报错
    • 并且,约定类型之后,代码的提示也会非常的清晰

    原始类型

    TS常用类型:

    • js已有类型
      • 简单类型:number , string , boolean , null ,undefined
      • 复杂类型 : 对象Object , 数组 Array ,函数Function
    • Ts新增类型
      • 联合类型 自定义类型(类型别名) , 接口 , 元组, 字面量类型 , 枚举 ,void , any , 泛型

    数组类型

    // 数组类型
    // 第一种写法【推荐】
    let numbers:number[] = [1,2,3];
    // 第二种写法
    let strings:Array = ["a","b","c"];
    
    • 1
    • 2
    • 3
    • 4
    • 5

    联合类型

    将多个类型合并为一个类型

    类型和类型之间使用 | 连接,代表类型可以是他们当中的其中一种,这种类型叫联合类型

    // 数组中有number 和string 如何写?
    let arr:(number | string |boolean)[] = [1,"hello",4,"456",true];
    
    // 给定时器加类型
    
    let timer:number | null = null; 
    timer= setInterval(()=>{},1000)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    类型别名

    使用类型别名语法给类型重新起名字

    当同一类型被多次使用时,可以通过类型别名,简化该类型的使用

    // 类型别名
    // let arr1:(number|string|boolean)[] =[1,2,"hello"];
    // 类型别名   type 类型别名 = 具体类型
    
    type CustomArr = (number | string | boolean)[];
    let arr1:CustomArr = [1,2,"hello",true];
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • type 类型别名 = 具体类型 基本语法
    • 定义类型别名,遵循大驼峰命名规范,类似于变量
    • 使用类型别名,与类型注解的写法一样即可

    函数类型

    给函数指定类型,就是给 参数和返回值 指定类型

    两种写法:

    • 在函数基础上 分别指定 参数和返回值类型
    • 使用类型别名 同时指定 参数和返回值的类型
    // - 在函数基础上 **分别指定** 参数和返回值类型
    
    // 函数声明
    function add(num1:number,num2:number):number{
        return num1 + num2
    }
    console.log(add(1,2));
    
    // 箭头函数
    const add1 = (num1:number,num2:number):number=>{
        return num1 + num2;
    }
    console.log(add1(3,4))
    
    
    // - 使用类型别名 **同时指定** 参数和返回值的类型   
    
    //只适用于函数表达式
    type AddFn = (num1:number ,num2:number) =>number
    
    const add2:AddFn =(num1,num2)=>{
        return num1 + num2;
    }
    
    console.log(add2(7,8));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    void类型

    void函数返回值类型

    如果函数没有返回值,定义函数类型时返回值类型为void

    如果函数没有返回值,且没有定义函数返回值类型的时候,默认是void

    // void类型
    // 如果函数没有返回值,定义函数类型时返回值类型为void
    const say = ():void=>{
        console.log("hi");
    }
    say()
    
    // 如果函数没有返回值,且没有定义函数返回值类型的时候,默认是void
    const say1 = ()=>{
        console.log("hhi");
    }
    
    say1()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 在js中如果没有返回值,默认返回的是undefined
    • 但是void 和undefined 在TypeScript中并不是一回事
    • 如果指定返回值类型是undefined 那返回值必须是undefined
    // 如果指定返回值类型是undefined 那返回值必须是undefined
    const add4 = ():undefined=>{
        return undefined;
    }
    
    • 1
    • 2
    • 3
    • 4

    使用 ? 将参数标记为可选

    如果函数的参数,可以传也可以不传,这种情况就可以使用 可选参数 语法,参数后加 即可

    const fn = (n?:number)=>{
        console.log(123)
    }
    fn();
    fn(3);
    
    • 1
    • 2
    • 3
    • 4
    • 5

    案例

    // 模拟slice函数, 定义函数参数类型
    // 注意:必须参数不能位于可选参数后面
    const mySlice = (start:number,end?:number) =>{
        console.log("起始index"+start+'结束index'+end)
    }
    
    mySlice(2)
    mySlice(4,5)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    对象类型

    TS的对象类型,其实就是描述对象中的属性 方法的类型,因为对象是由属性和方法组成的

    • 声明对象结构 {}
    • 属性怎么写类型 属性名: 类型
    • 方法怎么写类型 方法名():返回值类型
    // 空对象
    let person:{} = {}
    
    // 有属性的对象
    let person1:{name:string} = {
        name:"zs"
    }
    
    // 有属性和方法,一行书写多个属性  ; 分割
    let person2:{name:string;sayHi():void} = {
        name:"jack",
        sayHi(){}
    }
    
    // 换行写 可以省略 ; 符号
    let person3 :{
        name:string
        sayHi():void
    } = {
        name:"zs",
        sayHi(){}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    扩展

    对象类型中,函数使用箭头函数类型,属性设置可选,使用类型别名

    • 函数使用箭头函数类型

      let person5:{
         name:string
         sayHi:()=>void
      } = {
          name:"jack",
          sayHi(){}
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
    • 对象属性设置可选

      // axiois({url,method}) 如果是get 请求method 可以省略
      const axios =(config:{url:string;method?:string})=>{}
      
      • 1
      • 2
    • 使用类型别名

      // { } 会降低代码可阅读性,建议对象使用类型别名
      
      type Config = {
          url:string;
          method?:string
      }
      
      const axios1 =(config:Config) =>{}
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8

    接口interface

    使用interface声明对象类型

    接口声明是命名对象类型的另一种方式

    • interface 后面是接口名称,和类型别名的意思一样
    • 指定接口名称作为变量的类型使用
    • 接口的每一行只能由一个属性或方法,每一行的分号可以省略
    // 接口  interface声明对象类型
    
    interface Person{
        name:string;
        age:number;
        sayHi:()=>void
    }
    // 使用类型
    let person8:Person = {
        name:"zs",
        age:12,
        sayHi(){}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    interface继承

    使用extends实现接口继承,达到类型复用

    语法:interface 接口A extends 接口B { }

    继承后接口A拥有接口B的所有属性和函数的类型声明

    // interface 继承
    // 有两个接口,有相同的属性或函数,如何提高代码复用?
    // interface Point2D {
    //     x:number;
    //     y:number;
    // }
    // interface Point3D {
    //     x:number;
    //     y:number;
    //     z:number;
    // }
    // 继承  相同的属性或方法可以抽离出来,使用extends实现继承复用
    interface Point2D {
        x:number;
        y:number;
    }
    // 继承Point2D
    interface Point3D extends Point2D {
        z:number;
    }
    let p:Point3D ={
        x:12,
        y:23,
        z:56
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    type交叉类型

    交叉类型实现接口的继承效果

    使用 & 可以合并连接的对象类型 叫做交叉类型

    // type交叉类型
    // 使用type来定义Point2D 和Point3D
    type Point2D = {
        x:number;
        y:number;
    }
    
    // 使用交叉类型 来实现接口继承的功能
    type Point3D =Point2D & {
        z:number;
    }
    
    let o:Point3D= {
        x:1,
        y:2,
        z:3
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    interface vs type

    • 类型别名和接口非常相似,在很多情况下,可以在他们之间自由选择
    • 接口的几乎所有特性都以类型的形式可用,关键的区别在于不能重新打开类型以添加新属性,而接口总是可扩展的
    interfacetype
    支持:对象类型支持:对象类型 其他类型
    复用: 可以继承复用: 交叉类型

    不同点

    • type不可以重复定义
    • interface重复定义会合并
    type Point2D = {
        x:number;
        y:number;
    }
    // 标识符“Point2D”重复
    type Point2D = {
        age:number;
    }
    
    //-------------------------------------
    interface Point2D {
        x:number;
        y:number;
    }
    //类型会合并  注意:属性类型和方法类型不能重复定义
    interface Point2D {
       age:number
    }
    // 继承Point2D
    interface Point3D extends Point2D {
        z:number;
    }
    let p:Point3D ={
        x:12,
        y:23,
        z:56,
        age:78
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    类型推断

    • TS中存在类型推断机制,在没有指定类型的情况下,TS也会给变量提供类型

    开发项目时,能省略类型注解的地方就省略, 充分利用TS的类型推断能力,提高开发效率

    // 发生类型推断的几个场景
    
    // 变量a的类型被自动推断为 number
    let a = 18;
    
    // 函数的返回值类型被自动推断为 number
    const add3 = (num1:number,num2:number) =>{
        return num1 + num2
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    字面量类型

    js字面量如: 18 ‘jack’ [‘a’] {age:10} 等等

    使用js字面量作为变量类型,这种类型就是字面量类型

    // 'lucy' 是字面量类型
    let n:'lucy' = 'lucy';
    // 18 是字面量类型
    let n1:18 = 18;
    //   报错 不能将类型“19”分配给类型“18”
    // n1 = 19;
    
    let str1 = "hello";   //str1的类型是string
    const str2 = "hello"; //str2的类型是 "hello"  str2是const声明的 值只能是 "hello"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    字面量类型应用

    // 性别只能是男 和 女  不会出现其他值
    // let gender = '男';
    // gender = '女' 
    // 字面量类型 配合联合类型使用, 表示  一组明确的可选的值
    type Gender = '男' | '女';
    let gender:Gender = "男";
    gender = "女"
    
    type Direction = 'up' | 'down' | 'left' | 'right';
    
    
    // direction的只能是 up ,down ,left ,right 中的任意一个
    // 优点:使用字面量类型更加精确,严谨
    function changeDirection(direction:Direction){
        console.log(direction)
    }
    
    changeDirection('left');
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    any类型

    any类型的作用是逃避TS的类型检查

    显示any: 当变量的类型指定为any的时候,不会有任何错误,也不会有代码提示,TS会忽略类型检查

    隐式any:声明变量不给类型或初始值,函数参数不给类型或初始值

    any的使用越多,程序可能出现的漏洞越多,因此【不推荐】使用any类型,尽量避免使用

    // 显式any   
    let obj:any = {age:18}
    obj.bar = 100
    // 不会报错  将来可能出现错误
    obj = 23;
    
    // 隐式any
    let aa ;
    const fn5 = (n4) =>{}
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    类型断言

    • 使用关键字 实现类型断言
    • 关键字as后面的类型是一个更加具体的类型(HTMLAnchorElement 是 HTMLElement的子类型)

    有时候你会比ts更加明确一个值的类型,此时,可以使用类型断言来指定更具体的类型

    // alink的类型 HTMlElement,该类型只包含a元素特有的属性或方法 
    HTMLElement 使用这个类型 太宽泛 没包含a元素特有的属性或方法  href
    const alink = document.getElementById('link')
    <a id="link"></a>
    我们很明确alink 获取到的就是一个a元素,通过类型断言,给它指定一个更具体的类型
    const alink = document.getElementById('link') as HTMLAnchorElement
    const img= document.getElementById('img') as HTMLImageElement
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    泛型

    在ts中,泛型是一种创建可复用代码组件的工具,这种组件不只能被一种类型使用,而是能被多种类型复用类似于参数;

    泛型是一种用于 增强类型(types)接口(interfaces)函数类型等能力的非常可靠的手段

    泛型别名中使用泛型

    泛型: 定义类型别名后 加上 <类型参数> 就是泛型语法,使用时传入具体的类型即可

    是一个变量,可以随意命名,建议遵循大驼峰命名法

    和类型别名配合,在类型别名后加上泛型语法,然后类型别名内就可以使用这个类型参数

    泛型可以提高类型的复用性和灵活性

    type User = {
        name:string;
        age:number
    }
    
    type Goods = {
        id:number;
        goodsName:string;
    }
    
    type Data = {
        msg:string;
        code:number;
        data:T
    }
    
    // 使用类型
    type UserData = Data
    type GoodsData = Data
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    泛型接口

    • 在接口名称的后面加上<类型参数>,那么这个接口就编程了泛型接口,接口中所有成员都可以使用类型参数
    interface IdFn {
        id:()=>T;
        ids:()=>T[]
    }
    
    const idObj:IdFn = {
        id(){return 1},
        ids(){ return [1,2,3]}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    内置的泛型接口

    // 内置的泛型接口
    const  arr7 = ["a","b"]
    // Ts有类型推断能力  其实可以看作  const arr7:Array = [1,2,3]
    const arr8:Array = [1,2,3]
    // 通过Ctrl + 鼠标左键 去查看内置的泛型接口
    arr7.push("7")
    arr7.forEach(item=>(console.log(item)))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    泛型函数

    • 函数名称后面加上,T是类型参数
    • 当我们调用函数的时候,传入具体的类型,T捕获这个类型,函数任意位置都可以使用该类型
    • 好处
      • 让函数可以支持不同类型(复用),保证类型是安全的
      • 调用函数,传入的数据可以推断出你想要的类型,就可以省略泛型
    // 泛型函数
    function getId(id:T):T{
        return id
    }
    
    let id1 = getId(1)
    // TS会进行类型推断  参数的类型作为泛型的类型
    let id2 =getId("2")
    
    let id3 = getId({name:"zs"})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    枚举类型

    允许我们定义一组命名常量,使用枚举去创建一组不同的案例会变得更加容易,它是相关的集合,可以是数字值,也可以是字符串值

    // enum Direction {
    //   up,    // 0 
    //   down,  // 1 
    //   left,  // 2
    //   right  // 3
    // }
    
    // enum Direction {
    //   up = 1,    // 1 
    //   down,  // 2 
    //   left,  // 3
    //   right  // 4
    // }
    
    enum Direction {
      up = 'up',
      down = 'down',
      left = 'left',
      right = 'right'
    }
    console.log(Direction.down);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
  • 相关阅读:
    递归,动态规划实现
    IO流高级流
    真正靠谱的手机清理APP与方法,轻松帮你干掉几个G垃圾!
    Batch Normalization的优势
    Kubernetes(k8s)CNI(flannel)网络模型原理
    ssm毕设项目动态个人网站8j9pz(java+VUE+Mybatis+Maven+Mysql+sprnig)
    Java使用反射获取注解信息的简介说明
    软考考试为什么通过率不高?
    动态规划34(Leetcode337打家劫舍3)
    深入探索(淘宝1688京东)API商品详情数据:从价格到销量,一应俱全
  • 原文地址:https://blog.csdn.net/ioncannontic/article/details/133501619