zoukankan      html  css  js  c++  java
  • TypeScript——04——ts中的接口(Interface)

    一、前言

    TS新增了一个重要概念:接口,分为对象类型接口和函数类型接口
    接口可以约束对象,函数,类的结构和类型,是一种代码协作必须遵守的契约

    接口的定义方式:

    使用interface关键字

    二、对象类型接口

    接口中可定义 确定属性、可选属性、任意属性、只读属性

    1、确定属性
    复制代码
    interface UserInfo {
      name: string;
      age: number;
    }
    
    const myInfo: UserInfo = {
      name: "haha",
      age: 20
    };
    复制代码

    接口中约束好的确定属性,定义对象变量的时候 不能少也 不能多

    2、可选属性

    复制代码
    interface UserInfo {
      name: string;
      age: number;
      sex?:string 
    }
    
    const myInfo: UserInfo = {
      name: "haha",
      age: 20
    };
    复制代码

    接口中的可选属性,是表示在对象变量中可以不存在

    3、任意属性

    复制代码
    interface UserInfo {
      name: string;
      age: number;
      sex?:string ;
      [propName: string]:any;
    }
    
    const myInfo: UserInfo = {
      name: "haha",
      age: 20,
      test1: 'lala',
      test2: 'ff',
      test3:123
    };
    复制代码

    注:一旦定义了任意属性,那么确定属性和可选属性的类型都必须是任意属性类型的子类;

    定义了任意属性后,对象变量中的属性个数才可以出现比接口的属性数量多的情况

    4、只读属性

    复制代码
    interface UserInfo {
      readonly id: number;
      name: string;
      age: number;
      sex?: string;
      [propName: string]: any;
    }
    
    const myInfo: UserInfo = {
      id: 1,
      name: "haha",
      age: 20,
      test1: "lala",
      test2: "ff",
      test3: 123
    };
    复制代码

    只读属性也是确定属性,在对象变量定义的时候必须有值,此后不能修改

    对象接口示例

    以查询商品列表接口API为例:

    // 接口声明:API协议约定返回格式
    interface ResponseData {
        resCode: number;
        resData: ResultData[];
        message: string;
    }
    
    // 数据接口声明
    interface ResultData {
        productId: number;
        productName: string;
    }

    符合接口约定的对象:

    let resultData = {
        resCode: 0,
        resData: [
            { productId: 1, productName:"TypeScipt实战" },
            { productId: 2, productName:"TypeScipt从入门到精通" },
        ],
        message: "success"
    }

    输出函数对结果进行打印:

    function render(res: ResponseData) {
        console.log(res.resCode, res.message)
        res.resData.forEach((obj) => {
            console.log(obj.productId, obj.productName)
        })
    }
    
    render(resultData);

    输出:

    0 "success"
    1 "TypeScipt实战"
    2 "TypeScipt从入门到精通"

    额外属性

    在接口的实际调用中,后端也经常会传递约定之外的字段,比如:

    let resultData = {
        resCode: 0,
        resData: [
            { productId: 1, productName:"TypeScipt实战", remark:""}, // 接口约定以外的remark字段
            { productId: 2, productName:"TypeScipt从入门到精通" },
        ],
        message: "success"
    }

    此时,并没有报错,TS允许这种情况的发生

    只要传入的对象满足接口的必要条件就可以被允许,即使传入多余的字段也可以通过类型检查

    但也有例外,如果直接传入对象字面量,TS就会对额外的字段进行类型检查

    以下方式会报错:

    render({
        resCode: 0,
        resData: [
            { productId: 1, productName:"TypeScipt实战", remark: "备注"},
            { productId: 2, productName:"TypeScipt从入门到精通" },
        ],
        message: "success"
    })

     

    绕过检查的方法有3种:

    1,将对象字面量赋值给一个变量

    将对象字面量赋值给一个变量后,在render不再报错:

    let result = {
        resCode: 0,
        resData: [
            { productId: 1, productName:"TypeScipt实战", remark: "备注"},
            { productId: 2, productName:"TypeScipt从入门到精通" },
        ],
        message: "success"
    }
    render(result)
    2,使用类型断言
    使用类型断言方式,明确告诉编译器类型是什么,编译器就会绕过类型检查

    方法1:

    object as targetInterface
    render({
        resCode: 0,
        resData: [
            { productId: 1, productName:"TypeScipt实战", remark:""},
            { productId: 2, productName:"TypeScipt从入门到精通" },
        ],
        message: "success"
    } as ResponseData)

    方法二:

    <targetInterface>object
    render(<ResponseData>{
        resCode: 0,
        resData: [
            { productId: 1, productName:"TypeScipt实战", remark: "备注"},
            { productId: 2, productName:"TypeScipt从入门到精通" },
        ],
        message: "success"
    })
    3,使用字符串索引签名

    添加字符串索引签名:

    interface ResultData {
        productId: number;
        productName: string;
        [remark: string]: any;  // 字符串索引签名
    }
    表示用任意字符串去索引List,可得到任意结果,此时List可以实现支持多个属性

    三、函数接口

    函数定义方式

    1,在TS中,可以使用一个变量直接定义函数:

    // 1,使用变量定义函数
    let add: (x: number, y: number) => number
    = (x, y){
      return x+y;
    };
    add(1,2)

    2,还可以使用接口来定义函数:

    // 2,使用接口定义函数
    interface Add {
        (x: number, y: number): number
    }
    let myFunc: Add = function(x, y){
      return x+y;
    };
    myFunc(1,2);

    3,使用类型别名来定义函数:

    类型别名使用type关键字,相当于为函数类型起一个名字
    // 3,使用类型别名来定义函数
    type Add = (x: number, y: number) => number

    四、可索引类型的接口

    当不能确定接口中有多少个属性时,可以使用可索引类型接口
    可索引类型接口可以用数字去索引,也可以用字符串去索引
    1,数字索引接口:

    声明一个数字索引类型的接口:

    表示用任意数字去索引numberIndex都会得到一个string
    interface numberIndex {
        [x: number]: string
    }
    // 相当于声明了一个字符串类型的数组
    let chars: numberIndex = ['A', 'B']
    2,字符串索引接口:

    声明一个字符串索引类型的接口:

    表示用任意的字符串去索引stringIndex得到的结果都是string
    interface stringIndex {
        [x: string]: string
    }

    这样声明后,就不能声明number类型的成员了,会报错

    interface stringIndex {
        [x: string]: string
        y: number;// Property 'y' of type 'number' is not assignable to string index type 'string'.
    }
    3,两种索引签名混用:
    在上边的字符串索引接口stringIndex中,添加数字索引签名
    interface stringIndex {
        [x: string]: string
        [z: number]: string
    }
    这样做.接口既可以用数字索引Names也可以用字符串索引Names

    但需要注意:数字索引的返回值,一定要是字符串返回类型的子类型

    这是因为JS会进行类型转换,将number转换成string,这样就能保证类型的兼容性

    比如:将数组索引的返回值改成number:

    interface stringIndex {
        [x: string]: string
        [z: number]: number    // // Numeric index type 'number' is not assignable to string index type 'string'.
    }

    这样就和String类型不兼容了,要取一个能够兼容number的类型,比如any:

    interface stringIndex {
        [x: string]: any
        [z: number]: number // Numeric index type 'number' is not assignable to string index type 'string'.
    }
     
  • 相关阅读:
    1030 完美数列 (25 分)
    1029 旧键盘 (20 分)
    数据库命令失败原因汇总
    代码有中文括号,导致错误
    win10笔记本触控板使用指南
    (已解决)vsC#控制台应用添加System.Windows.Forms引用失败(精通C#)
    ildasm中Ctrl+M闪退的问题(已解决, 精通C# 15.1)
    C#控制台应用(.NET Core)添加System.Windows.Forms失败(已解决)
    知识点_指针_增加对指针的理解
    自己写出的Bug_应是%f却写成%d
  • 原文地址:https://www.cnblogs.com/xuelanying/p/14411850.html
Copyright © 2011-2022 走看看