《三》大話 Typescript 接口

前言: 本文章爲 TypeScript 系列文章. 旨在利用碎片時間快速入門 Typescript. 或從新溫故 Typescript 查漏補缺.在官方 api 的基礎上, 加上一些平常使用的感想. 若是感興趣的話~ 歡迎關注, 後續持續推出文章.javascript

文章列表:前端

目錄結構:java

  • 接口對象的基本屬性
  • 接口聲明方式
  • 可索引類型接口
  • 接口繼承接口
  • 接口實現

接口類型是一個很是強大的類型定義,是在平常代碼中常常會使用到的的一個功能. 系統的瞭解他很是的重要.react

接口對象的基本屬性

接口對象的屬性有正常屬性, 可選屬性, 只讀屬性 , 以下代碼:api

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 爲上面的數據類型 ]bash

這個 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) //不報錯
複製代碼
  1. 類型斷言 這個特性也常常會使用, 學起來. 直接到傳的參數後面調用 as LearnList, 告訴編輯器, 咱們明確知道這個對象是 LearnList 的,請繞過這個檢查.
transformData({
    subject: 'math',
    xxx: 'sss', 
    detail: [{
        id: 1,
        data: '數學'
    }]
} as LearnList )
複製代碼
  1. 字符串索引簽名. 看下面

可索引類型接口

從上面的問題看出, 在原有的對象聲明中多一個屬性就報錯了. 有些場景咱們可能對入參的參數比較靈活, 除了咱們規定的一些參數, 不肯定還會傳其餘什麼參數進來的時候, 可使用 「可索引類型接口」

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; // 表示能夠用任意字符串去索引 對象, 獲得一個字符串的值 
}
複製代碼
  1. 用數字索引的接口
interface StringArray {
    [x: number]: string; // 用任意的 number 去索引對象, 都會獲得一個 string 類型. 其實就是咱們的數組了 
}
複製代碼
  1. 混用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() { }
}
複製代碼
  1. 類實現接口時 ,必須實現接口中全部的屬性
interface Point {
    x: number;
    draw(): void;
}

class Draw implements Point {
    constructor() {

    }
    x: number;  
    draw() { } // 若是這行不見了,就會報錯
}
複製代碼
  1. 接口沒法約束類的構造函數
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 更加靈活. 秉承着一篇文章不能太長的原則. 今天就到這裏結束了. 感興趣能夠關注我~ 長期連載

最後 歡迎加我微信(A18814127),拉你進技術羣,長期交流學習... 歡迎關注「前端加加」,認真學前端,作個有專業的技術人...

相關文章
相關標籤/搜索