• typescript-TS中的兼容性(十二)


    自动类型推论

    概述

    • 根据初始化进行类型推论
      • 不用明确告诉编译器具体是什么类型,编译器就知道是什么类型
      • 根据初始化值自动推断
      • 注意点: 如果先定义在初始化,那么是无法自动推断
      // 相当于 let x: (number | null)[] = [0,1,null]
      let x = [0,1,null]
      // x = [20,30,60,null,"zs"]  // error,"zs"是属于字符串类型
      
      // 不能进行类型推论
      let uage;
      uage = 123
      uage = true
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
    • 上下文类型推断
      • 上下文类型推断
      window.onmousedown = function(mouseEvent){
        mouseEvent.button
        mouseEvent.clientX
      }
      
      • 1
      • 2
      • 3
      • 4

    对象类型兼容性

    对象类型兼容性(可多不可少)

    interface INameTest{
      name: string
    }
    
    let n1 = {name: "法外狂徒张三"}
    let n2 = {name: "zs",age: 18}
    let n3 = {age: 19}
    
    let val: INameTest
    val = n1
    val = n2
    // val = n3 // error,类型 "{ age: number; }" 中缺少属性 "name",但类型 "INameTest" 中需要该属性
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    对象类型兼容性(类型必须一一对应)

    // 注意点  类型必须一一对应,ts内部会进行递归检查
    interface ITestInfo{
      name: string
      children: {
        age: number
      }
    }
    
    let p1 = {name: 'zs',children: {age: 19}}
    let p2 = {name: 'zs',children: {age: true}}
    
    let person: ITestInfo;
    person = p1
    // person = p2 //error,不能将类型“{ name: string; children: { age: boolean; }; }”分配给类型“ITestInfo”。在这些类型中,"children.age" 的类型不兼容。不能将类型“boolean”分配给类型“number”
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    函数类型兼容性

    参数个数

    let func1 = (x: number,b: string) =>{}
    let func2 = (x: number) =>{}
    
    // 注意点: 可多不可少
    func1 = func2
    // func2 = func1 // error,不能将类型“(x: number, b: string) => void”分配给类型“(x: number) => void”
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    参数类型

    let func3 = (x: number) =>{}
    let func4 = (x: string) =>{}
    let func5 = (x: number) =>{}
    
    
    // 注意点: 参数类型一致
    // func3 = func4 // error,不能将类型“(x: string) => void”分配给类型“(x: number) => void”。参数“x”和“x” 的类型不兼容。不能将类型“number”分配给类型“string”
    func3 = func5
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    参数返回值

    let func6 = (): number => 23
    let func7 = (): number => 13
    let func8 = (): string => "返回值类型的兼容性"
    
    // 注意点: 返回值类型必须一致
    func6 = func7
    // func6 = func8 // error,不能将类型“() => string”分配给类型“() => number”。不能将类型“string”分配给类型“number”
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    双向协变

    // 1.参数的双向协变
    let funct1 = (x: number) => {}
    let funct2 = (x: (number | string)) => {}
    
    
    // 注意点: 可以将多的赋值给少的
    funct1 = funct2
    // funct2 =funct1  // 不能将类型“(x: number) => void”分配给类型“(x: (number | string)) => void”。参数“x”和“x” 的类型不兼容。不能将类型“string | number”分配给类型“number”。不能将类型“string”分配给类型“number”
    
    // 2.返回值的双向协变
    
    let funct3 = (x: boolean): (number | string) => x? 18 : 'zs'
    let funct4 = (x: boolean): number => 18
    
    // 注意点: 不能将返回值是联合类型的赋值给具体的
    funct3 = funct4
    // funct4 = funct3 // error,不能将类型“(x: boolean) => (number | string)”分配给类型“(x: boolean) => number”。不能将类型“string | number”分配给类型“number”。不能将类型“string”分配给类型“number”
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    函数重载

    function add(x: number,y: number): number
    function add(x: string,y: string): string
    function add(x: any,y: any): any {
      return x+y
    }
    
    function sub(x: number,y: number): number
    function sub(x: any,y: any): any{
      return x-y
    }
    // 注意点: 不能将重载少,赋值给重载多的(包含关系)
    
    let fna = add
    let fns = sub
    // fna = fns //error,不能将类型“(x: number, y: number) => number”分配给类型“{ (x: number, y: number): number; (x: string, y: string): string; }”。参数“x”和“x” 的类型不兼容。不能将类型“string”分配给类型“number”
    fns = fna
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    可选参数及剩余参数

    // 当一个函数有剩余参数的时候,被当做无限个可选参数
    function func(args: any[],callback: (...args: any[]) => void) {}
    func([1,2],(x,y,z) => console.log(x+y+z))
    func([1,2],(x?,y?) => console.log(x+y))
    func([1,2],(x,y?,z?) => console.log(x+y))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    
    
    
    • 1
    • 2

    枚举类型知识补充

    数据枚举类型

    • 数字枚举的取值可以是字面量,也可以是常量,也可以是计算的结果
    • 如果采用字面量对第一个成员进行赋值,下面的成员会自动递增
    • 如果采用常量计算结果进行赋值,则下面的成员也必须初始化
    // 数字枚举
    enum Gender {
      Male,
      Female
    }
    console.log(Gender.Male,Gender.Female) // 0 1
    console.log(Gender[0]) // Male
    
    
    const val = 100
    const num = () => 200
    enum Gender_1 {
      // 常量
      Male = val,
      // 计算结果
      Female = num()
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    字符串枚举类型

    • 如果采用字面量对第一个成员进行赋值,下面的成员也必须赋值
    • 采用[index]的形式不能获取到内容,需要传入[key]
    • 字符串枚举不能使用常量计算结果给枚举值赋值
    • 它可以使用内部的其他枚举值来赋值
    enum Direction {
      up = "UP",
      down = "DOWN"
    }
    console.log(Direction.up)// UP
    // console.log(Direction[0]) // error,元素隐式具有 "any" 类型,因为类型为 "0" 的表达式不能用于索引类型 "typeof Direction"。类型“typeof Direction”上不存在属性“0”
    console.log(Direction["up"])// UP
    
    const str = "法外狂徒张三"
    const res = () => "鬼脚七"
    enum Star{
      // desc = str //error,只有数字枚举可具有计算成员,但此表达式的类型为“"法外狂徒张三"”。如果不需要全面性检查,请考虑改用对象文本
      // desc = res //error,只有数字枚举可具有计算成员,但此表达式的类型为“() => string”。如果不需要全面性检查,请考虑改用对象文本
      desc = "太极宗师",
      tagDesc = desc
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    异构枚举(数字+字符串)

    • 如果是字符串枚举,那么无法通过原始值获取到枚举值
    enum  Person{
      Male = 1,
      Female = '女'
    }
    console.log(Person.Male) // 1
    console.log(Person.Female) // 女
    console.log(Person[0]) // undefined
    console.log(Person["Male"]) // 1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    把枚举成员当作类型来使用

    enum Gender_2{
      Male,
      Female
    }
    interface PersonInfo{
      sex: Gender_2 // sex: (Gender_2.Male | Gender_2.Female)
    }
    
    class Persons implements PersonInfo{
      sex: Gender_2.Female = 1
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    枚举类型兼容性

    数字枚举与数字兼容

    enum Gender{
     Male,
     Female 
    }
    
    let value: Gender;
    value = Gender.Male
    value = 100
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    数字枚举与数字枚举不兼容

    enum Gender{
     Male,
     Female 
    }
    
    enum Animal{
      Dog,
      Cat
    }
    
    let value: Gender
    value = Gender.Female
    // value = Animal.Dog // error,不能将类型“Animal.Dog”分配给类型“Gender”
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    字符串枚举与字符串不兼容

    enum Gender{
      Male = "法外狂徒张三",
      Female = "李寒冰"
    }
    let value: Gender
    value = Gender.Male
    value = Gender.Female
    
    // value = "赵玉道" // error,不能将类型“"赵玉道"”分配给类型“Gender”
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    
    
    
    
    • 1
    • 2
    • 3

    类的兼容性

    • 类的工作方式与对象字面类型和接口类似,但有一个不同点: 他们同时具有静态实例类型时,当比较一个类类型的两个对象时,只有实例的成员被比较静态成员构造函数不影响兼容性
    • 一个类中的私有成员保护成员会影响兼容性。当一个类的实例被检查兼容性时,如果目标类型包含一个私有成员,那么原类型也必须包含一个源自同一个类的私有成员(保护成员同上)
    • public可多不可少
    • private/protected不能相互赋值

    类的兼容性—可多不可少

    // 可多不可少
    class Animal{
      feet: number
      age: number
      constructor(feet: number,age: number){
        this.feet = feet
        this.age = age
      }
    }
    class Size{
      feet: number
      constructor(numFeet: number){
        this.feet = numFeet
      }
    }
    let anm: Animal
    let si: Size
    
    // anm = si // error,类型 "Size" 中缺少属性 "age",但类型 "Animal" 中需要该属性。
    si = anm
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    类的兼容性—private/protected

    class Animal{
      private feet: number
      constructor(name: string,numFeet: number){
        this.feet = numFeet
      }
    }
    class Size{
      private feet: number
      constructor(numFeet: number){
        this.feet = numFeet
      }
    }
    let anm: Animal
    let si: Size
    
    // si = anm // error,不能将类型“Animal”分配给类型“Size”。类型具有私有属性“feet”的单独声明
    // anm = si // 不能将类型“Size”分配给类型“Animal”。类型具有私有属性“feet”的单独声明
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    泛型的兼容性

    // TS是一个结构化的类型系统,类型参数只在作为成员类型的一部分被消耗是影响到结果类型
    interface Empty<T> {}
    
    let x: Empty<number>
    let y: Empty<string>
    
    x = y
    y = x
    
    
    interface NotEmpty<T>{
      data: T
    }
    
    let x1: NotEmpty<string>
    let y1: NotEmpty<number>
    
    // x1 = y1 // error,不能将类型“NotEmpty”分配给类型“NotEmpty”。不能将类型“number”分配给类型“string”
    // y1 = x1 // error,不能将类型“NotEmpty”分配给类型“NotEmpty”。不能将类型“string”分配给类型“number”
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
  • 相关阅读:
    【图像分类】2021-MLP-Mixer NIPS
    堆排序与优先队列
    15链表-交换节点
    理德外汇:美长债收益率再次向5%迈进 提振美元同时压制股市
    uniapp 小程序图片懒加载组件 ImageLazyLoad
    elementui- Select 选择器-案例: 在v-for循环的多个下拉列表选择后需要传递对应的名字和id
    【再探】设计模式-设计原则
    记录第一次
    协议(网络协议)
    gitHub添加ssh
  • 原文地址:https://blog.csdn.net/qq_39656068/article/details/126027401