zoukankan      html  css  js  c++  java
  • 《三》大话 Typescript 接口

    > 前言: 本文章为 TypeScript 系列文章. 旨在利用碎片时间快速入门 Typescript. 或重新温故 Typescript 查漏补缺.在官方 api 的基础上, 加上一些日常使用的感想. 如果感兴趣的话~ 欢迎关注, 后续持续推出文章.

    文章列表:

    - 《一》大话 TypeScript 基本类型
    - 《二》大话 Typescript 枚举
    - 《三》大话 Typescript 接口
    - 《四》大话 Typescript 泛型
    - 《五》大话 Typescript 函数
    - 《六》大话 Typescript 类
    - 《七》大话 Typescript react 类
    - 《八》大话 Typescript react 函数
    - ……

    目录结构:
    - 接口对象的基本属性
    - 接口声明方式
    - 可索引类型接口
    - 接口继承接口
    - 接口实现


    接口类型是一个非常强大的类型定义,是在日常代码中经常会使用到的的一个功能. 系统的了解他非常的重要.


    #### 接口对象的基本属性
    接口对象的属性有正常属性, 可选属性, 只读属性 , 如下代码:
    ```
    interface List {
    readonly id: number; // 不可修改, 只可读取
    name?: string; // 可以有, 可以没有
    data: string; // 一定要有
    eat(): void; // 也可以声明一个函数
    }

    let a: List = {
    id: 1,
    data: 'msg'
    }


    a.id = 2;
    // 报错: Cannot assign to 'id' because it is a constant or a read-only property.

    let b: List = {
    id: 1
    }
    // Type '{ id: number; }' is not assignable to type 'List'.
    // Property 'data' is missing in type '{ id: number; }'.
    // 报错: 缺少 data 属性
    ```

    #### 接口声明方式
    接口的声明和使用方式特别简单, 回顾第一篇文章的声明方式.

    (变量/函数): type // [type 为上面的数据类型 ]

    这个 type 可以是普通的类型, 也可以是一个 interface 接口, 大概有以下三种使用方式. 如下:
    ```
    interface List {
    data: string;
    }
    // 声明一个对象
    let obj: List = {data: 'msg'}

    // 函数声明参数, 返回值
    function a (x: List):List {
    return x;
    }

    // 类实现接口, 类似于 java 语言, 在接口描述一个方法,在类里实现它
    // 这种方式一般很少使用他, 不过可以了解一下
    class Crazy implements List {
    constructor() {}
    data: string;
    }
    ```
    日常使用我们经常会有一些嵌套对象, 比如拿到后台接口的格式是这样子的.
    ```
    let res = {
    subject: 'math',
    detail:[{
    id: 1,
    data: '数学'
    }]
    }
    ```
    interface 是一个很灵活的属性. 可以多层嵌套.我们可以用下面的方式来定义,
    ```
    interface List {
    id: number;
    data: string;
    }
    interface LearnList {
    subject: string,
    detail: List[];
    }
    let res: LearnList = {
    subject: 'math',
    detail: [{
    id: 1,
    data: '数学'
    }]
    }
    ```
    如果作为函数参数声明的话, 会有一个有意思的地方. 我们直接传值的话, 会有报错提示. 那如何解决这个报错提示? 在不修改 interface 声明的情况 ?
    ```
    function transformData(data: LearnList) {
    return data;
    }
    transformData({
    subject: 'math',
    xxx: 'sss', //报错, 多了一个属性
    detail: [{
    id: 1,
    data: '数学'
    }]
    })
    ```
    解决方法:
    1. 将值赋值给一个对象.
    这里涉及到一个类型兼容性, 后面的文章会详细讲. 此处大概讲一下. 也就是 cache 他有 LearnList 声明的对象里面的所有属性, 那 cache 兼容 LearnList 声明的对象, cache 也就可以赋值给 LearnList声明的对象.
    ```
    const cache = {
    subject: 'math',
    xxx: 'sss', //报错, 多了一个属性
    detail: [{
    id: 1,
    data: '数学'
    }]
    };
    transformData(cache) //不报错
    ```
    2. 类型断言
    这个特性也经常会使用, 学起来. 直接到传的参数后面调用 as LearnList, 告诉编辑器, 我们明确知道这个对象是 LearnList 的,请绕过这个检查.
    ```
    transformData({
    subject: 'math',
    xxx: 'sss',
    detail: [{
    id: 1,
    data: '数学'
    }]
    } as LearnList )
    ```

    3. 字符串索引签名.
    看下面


    #### 可索引类型接口
    从上面的问题看出, 在原有的对象声明中多一个属性就报错了. 有些场景我们可能对入参的参数比较灵活, 除了我们规定的一些参数, 不确定还会传其他什么参数进来的时候, 可以使用 “可索引类型接口”
    ```
    interface List {
    id: number;
    data: string;
    }
    interface LearnList {
    subject: string,
    detail: List[];
    [x: string]: any; // 可以用任意的string类型去索引声明的对象, 值是any类型
    }
    transformData({
    subject: 'math',
    xxx: 'sss',
    detail: [{
    id: 1,
    data: '数学'
    }]
    })
    ```
    这样也可以解决上面的问题. 下面来简单梳理下 可索引类型接口.
    1. 用字符串索引的接口
    ```
    interface StringArray {
    [x: string]: string; // 表示可以用任意字符串去索引 对象, 得到一个字符串的值
    }
    ```
    2. 用数字索引的接口
    ```
    interface StringArray {
    [x: number]: string; // 用任意的 number 去索引对象, 都会得到一个 string 类型. 其实就是我们的数组了
    }
    ```
    3. 混用2种索引
    ```
    interface StringArray {
    [x: string]: string;
    [z: number]: string;
    }
    let x: StringArray = {
    1: '2323',
    '2':'23423'
    } // 既可以用字符串索引也可以用数字索引
    ```
    注意点: 不管是数字索引还是字符串索引, 下面的索引值类型, 必须是上面索引的 子类型. 因为我们已经规定了任意的索引得到的值都是 string , 此时任何一个成员的值变成 number 都会报错.
    ```
    interface StringArray {
    [x: string]: string;
    [z: number]: string;
    y: 22; //报错 : Property 'y' of type '22' is not assignable to string index type 'string'
    }
    interface StringArray {
    [x: string]: string;
    [z: number]: number; //报错 因为 string 不兼容 number
    }
    interface StringArray {
    [x: string]: any;
    [z: number]: number; //正常· any 兼容 number
    }
    ```

    #### 接口继承接口
    跟类的继承语法是一样的. 直接看代码
    ```
    interface Point {
    x: number;
    }
    // 继承一个接口直接 extends
    interface Draw extends Point {
    y: number;
    }
    interface Shape {
    draw(): void;
    }

    //继承多个接口用逗号 , 隔开
    //同样的,他可以被反复 extends
    interface Human extends Draw, Shape { }

    // 必须具有继承接口的所有属性
    let peen: Human = {
    x: 1,
    y: 1,
    draw: () => { },
    }
    ```

    #### 接口实现

    这一块其实是相对于 javascript 而言, 引入了 java 的一些属性. 比如 implements. 这一块在实际项目中其实很少用到. 但还是简单讲一下.

    注意点:
    1. 接口只能描述类的公共部分,不能描述私有成员
    ```
    interface Point {
    x: number;
    draw(): void;
    }

    class Draw implements Point {
    constructor() {

    }
    private x: number; //报错 Class 'Draw' incorrectly implements interface 'Point'. Property 'x' is private in type 'Draw' but not in type 'Point'.
    draw() { }
    }
    ```
    2. 类实现接口时 ,必须实现接口中所有的属性
    ```
    interface Point {
    x: number;
    draw(): void;
    }

    class Draw implements Point {
    constructor() {

    }
    x: number;
    draw() { } // 如果这行不见了,就会报错
    }
    ```
    3. 接口无法约束类的构造函数
    ```
    interface Point {
    x: number;
    draw(): void;
    new(x: number): void; // 报错. 不用写这个
    }

    class Draw implements Point {
    constructor(x: number) {
    this.x = x;
    }
    x: number;
    draw() { }
    }
    ```


    #### 总结
    这篇文章主要是列举了 interface 的一些常见用法. 其实在实际运用中, 我们会用更方便的方式去使用他, 比如 Partial<interface> 全部让参数变成可选, 或者使用交叉类型联合类型让 interface 更加灵活. 秉承着一篇文章不能太长的原则. 今天就到这里结束了. 感兴趣可以关注我~ 长期连载


    最后
    欢迎关注「前端加加」,认真学前端,做个有专业的技术人...

  • 相关阅读:
    Mac查看某个文件的中某关键字信息
    Mac查看所有的文件
    Mac查看当前用户的环境变量
    Mac安装maven
    Lombok使用坑之属性不区分大小写
    Mac常用软件列表
    Mac系统升级
    Mac安装Git
    Mac查看git的安装路径
    Mac安装JDK8
  • 原文地址:https://www.cnblogs.com/beidan/p/12027401.html
Copyright © 2011-2022 走看看