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'.
}

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM