1. 程式人生 > 實用技巧 >TypeScript之介面&函式

TypeScript之介面&函式

TypeScript之介面&函式

一、什麼是介面?

在面嚮物件語言中,介面(Interfaces)是一個很重要的概念,它是對行為的抽象,而具體如何行動需要由類(classes)去實現(implements)。

TypeScript 中的介面是一個非常靈活的概念,除了可用於對類的一部分行為進行抽象以外,也常用於對「物件的形狀(Shape)」進行描述。

二、介面的實現

// 用介面定義物件
interface List {
	name: string,
    age: number,  // 必選屬性
    job?: string, //可選屬性,表示不是必須的引數,
    readonly id: number; // readonly 只讀屬性
    [ propName : string ] : any,  // 任意型別
}

interface Result {
    data: List[]
}

function render(result: Result){
    result.data.forEach(value => {
        console.log(value.id, value.name)
        if(value.age){
            console.log(value.age)
        }
        // value.id ++ 
    })
}

let result = {
    data: [
        {id: 1, name: 'A', age: 12, sex: 'male'},
        {id: 2, name: 'B', age: 10}
    ]
}

render(result)

上面例子中的就是一個介面的例項,利用介面約束了接收變數的型別,注意,在賦值時:變數的型別必須和介面的形狀保持一致。
介面型別有以下幾種屬性可選

  • 必選屬性 => ":" 帶冒號的屬性是必須存在的,不可以多也不能少

  • 可選屬性 => " ? " 表示有選擇的選項,可有可無

  • 只讀屬性 => " readonly " 物件的欄位只在建立的時候賦值,注意哦,注意,只讀的約束存在於第一次給物件賦值的時候,而不是第一次給只讀屬性賦值的時候:

  • 任意屬性 [ propName : 型別 ] : any 表示定義了任意屬性取string 型別的值

三、可索引介面:陣列、物件的約束(不常用)

1、對陣列的約束
interface StringArray {
    [index: number]: string;
} // 用任意的number去索引StringArray,最後得到的是一個字串的陣列

let chars: StringArray = ['A', 'B']
interface Names { 
    // [x: string]: string  // 字串索引簽名
    [x: string]: any
    // y: number
    // [z: number]: string  // 數字索引簽名
    [z: number]: number  
}

注:數字索引簽名的返回值一定是字串索引簽名返回值的子型別,因為js會進行轉換,將number轉換成string,保證型別的相容性

2、對物件的約束
interface UserObj{
    [index : string] : string // 討論點:為啥一定是string,而不能是number
}
var arr : UserObj = { name : '張三' };

四、函式的定義

1、函式宣告
function add1(x: number, y: string) : string {
    return x + y
}
console.log('add1', add1(3, '4'))

形式和JavaScript中的函式宣告一樣,但不一樣的是:

  • 指定了引數的型別(因為有型別檢查,所以要遵循),隨後指定了返回值的型別,這個時候返回值型別可以省略,因為typescript會根據返回語句自動推斷出返回值的型別。
  • 引數不可多不可少,只能剛剛好,且和順序有關。
2、函式宣告的方式有哪些?
function add1(x: number, y: string)  {
    return x + y
}

let add2: (x: number, y: number) => number

type add3 = (x: number, y: number) => number

interface add4 {
    (x: number, y: number): number
}

3、函式表示式

1)左邊的student的型別定義是通過賦值操作進行型別推論而推斷出來的,並沒有給student指定型別定義。

let student = function(x:string,y:number):string{
    return `我是${x},今年${y}歲`;
} 
console.log(student("wzy",22));  // 我是wzy,今年22歲

2)如果要給student指定型別的話,應該是這樣:

let student:(x:string,y:number)=>string = function(x:string,y:number):string{
    return `我是${x},今年${y}歲`;
}
console.log(student("wzy",22)); // 我是wzy,今年22歲

注:1.前後引數名稱可以不一致

2.當沒有返回值的時候使用void

4、定義一個可選引數
function add5(x : number, y ?: number){
    return y ? x + y : x;
}

add5(4)

之前提到過函式的引數是不可多不可少的,但是也可以像介面那樣的形式用?表示可選引數

注:可選引數必須位於必需引數後

5、定義預設引數
function add6(x: number, y = 0, z: number, q = 1){
    return x + y + z + q
}  

add6(2, undefined, 4)

注:必傳引數前的預設引數必傳,如果沒有,用undefined代替

6、定義剩餘引數
function add7(x : number, ...rest: number[]){ // 剩餘引數,即不知道引數的個數
    return x + rest.reduce((pre, cur) => pre + cur)
}

console.log(add7(1,2,3,4,5))

當你想同時操作多個引數或者你並不知道會有多少個引數會傳進來時可以採用剩餘引數定義

  • 在JavaScript中,可以使用arguments來訪問所有傳入的引數。

  • 在typescript裡,可以把所有引數收集到一個變數裡

注:

(1)剩餘引數會被當做個數不限的可選引數,可以一個都沒有,也可以有任意個。同樣要放在必要引數後面。

(2)是陣列型別,名字是省略號後面的欄位名,可以在函式體內使用這個陣列。

(3)當呼叫函式時,別傳入陣列,依次傳入就行。

7、函式過載(不需要為相似函式選取不同的函式名稱)
function add8(...rest: number[]) : number;
function add8(...rest: string[]) : string;
function add8(...rest: any[]) : any {
    let first = rest[0];
    if(typeof first === 'string'){
        return rest.join('')
    }
    if(typeof first === 'number'){
        return rest.reduce((pre, cur) => pre + cur)
    }
}
console.log(add8(1,2,3))
console.log(add8('2','add', 'asd'))

注:TypeScript 會優先從最前面的函式定義開始匹配,所以多個函式定義如果有包含關係,需要優先把精確的定義寫在前面。