TypeScript簡單入門(九):TypeScript函數(shù)的類型

函數(shù)聲明
在 JavaScript 中,有兩種常見的定義函數(shù)的方式——函數(shù)聲明(Function Declaration)和函數(shù)表達式(Function Expression):
函數(shù)聲明(Function Declaration)

 function sum(x,y){
     return x + y;
 }

函數(shù)表達式(Function Expression)

 let mySum = function (x,y){
     return x+y;
}

一個函數(shù)有輸入和輸出,要在 TypeScript 中對其進行約束,需要把輸入和輸出都考慮到,其中函數(shù)聲明的類型定義較簡單:

function sum(x:number,y:number):number{
     return x+y;
 };
//注意,輸入多余的(或者少于要求的)參數(shù),是不被允許的:
sum(1,2,3,)//Expected 2 arguments, but got 3.
sum(1);//Expected 2 arguments, but got 1.

函數(shù)表達式

如果要我們現(xiàn)在寫一個對函數(shù)表達式(Function Expression)的定義,可能會寫成這樣:

let mySum=function (x:number,y:number):number{
     return x+y;
 };

這是可以通過編譯的,不過事實上,上面的代碼只對等號右側(cè)的匿名函數(shù)進行了類型定義,而等號左邊的 mySum,是通過賦值操作進行類型推論而推斷出來的。如果需要我們手動給 mySum 添加類型,則應(yīng)該是這樣:

 let mySum:(x:number,y:number)=>number=function (x:number,y:number):number{
     return x+y;
 };

注意不要混淆了 TypeScript 中的 => 和 ES6 中的 =>。
在 TypeScript 的類型定義中,=> 用來表示函數(shù)的定義,左邊是輸入類型,需要用括號括起來,右邊是輸出類型。

用接口定義函數(shù)的形狀
我們也可以使用接口的方式來定義一個函數(shù)需要符合的形狀:

interface SearchFunc{
    (source:string,subString:string):boolean;
}
let mySearch:SearchFunc;
mySearch=function (source:string,subString:string){
    return source.search(subString)!==-1;
}

采用函數(shù)表達式|接口定義函數(shù)的方式時,對等號左側(cè)進行類型限制,可以保證以后對函數(shù)名賦值時保證參數(shù)個數(shù)、參數(shù)類型、返回值類型不變。

可選參數(shù)
前面提到,輸入多余的(或者少于要求的)參數(shù),是不允許的。那么如何定義可選的參數(shù)呢?與接口中的可選屬性類似,我們用 ? 表示可選的參數(shù):

function buildName(firstName: string, lastName?: string) {
     if (lastName) {
         return firstName + ' ' + lastName;
     } else {
         return firstName;
     }
 }
 let tomcat = buildName('Tom', 'Cat');
 let tom = buildName('Tom');

需要注意的是,可選參數(shù)必須接在必需參數(shù)后面。換句話說,可選參數(shù)后面不允許再出現(xiàn)必需參數(shù)了:

 function buildName(firstName?: string, lastName: string) {
     if (firstName) {
         return firstName + ' ' + lastName;
     } else {
         return lastName;
     }
 }
 let tomcat = buildName('Tom', 'Cat');
 let tom = buildName(undefined, 'Tom');//A required parameter cannot follow an optional parameter.

參數(shù)默認(rèn)值
在 ES6 中,我們允許給函數(shù)的參數(shù)添加默認(rèn)值,TypeScript 會將添加了默認(rèn)值的參數(shù)識別為可選參數(shù):

 function buildName(firstName:string,lastName:string='Cat'){
     return firstName+''+lastName;
 }
 let tomcat = buildName('Tom', 'Cat');
 let tom = buildName('Tom');

此時就不受「可選參數(shù)必須接在必需參數(shù)后面」的限制了:

 function buildName(firstName: string = 'Tom', lastName: string) {
     return firstName + ' ' + lastName;
 }
 let tomcat = buildName('Tom', 'Cat');
 let cat = buildName(undefined, 'Cat');

剩余參數(shù)
ES6 中,可以使用 ...rest 的方式獲取函數(shù)中的剩余參數(shù)(rest 參數(shù)):

 function push(array, ...items) {
     items.forEach(function(item) {
         array.push(item);
     });
 }

 let a: any[] = [];
 push(a, 1, 2, 3);

事實上,items 是一個數(shù)組。所以我們可以用數(shù)組的類型來定義它:

function push(array: any[], ...items: any[]) {
    items.forEach(function(item) {
        array.push(item);
    });
}

let a = [];
push(a, 1, 2, 3);

注意,rest 參數(shù)只能是最后一個參數(shù)

重載
重載允許一個函數(shù)接受不同數(shù)量或類型的參數(shù)時,作出不同的處理。
比如,我們需要實現(xiàn)一個函數(shù) reverse,輸入數(shù)字 123 的時候,輸出反轉(zhuǎn)的數(shù)字 321,輸入字符串 'hello' 的時候,輸出反轉(zhuǎn)的字符串 'olleh'。
利用聯(lián)合類型,我們可以這么實現(xiàn):

 function reverse(x:number|string):number|string|void{
     if(typeof x==='number'){
         return Number(x.toString().split('').reverse().join(''));
     } else if (typeof x==='string'){
         return x.split('').reverse().join('');
     }
 }

然而這樣有一個缺點,就是不能夠精確的表達,輸入為數(shù)字的時候,輸出也應(yīng)該為數(shù)字,輸入為字符串的時候,輸出也應(yīng)該為字符串。

這時,我們可以使用重載定義多個 reverse 的函數(shù)類型:

function reverse(x: number): number;
function reverse(x: string): string;
function reverse(x: number | string): number | string | void {
    if (typeof x === 'number') {
        return Number(x.toString().split('').reverse().join(''));
    } else if (typeof x === 'string') {
        return x.split('').reverse().join('');
    }
}

上例中,我們重復(fù)定義了多次函數(shù) reverse,前幾次都是函數(shù)定義,最后一次是函數(shù)實現(xiàn)。在編輯器的代碼提示中,可以正確的看到前兩個提示。

注意,TypeScript 會優(yōu)先從最前面的函數(shù)定義開始匹配,所以多個函數(shù)定義如果有包含關(guān)系,需要優(yōu)先把精確的定義寫在前面。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容