//在 JavaScript 中,有兩種常見的定義函數的方式——函數聲明(Function Declaration)和函數表達式(Function Expression): // 函數聲明(Function Declaration) function sum(x, y) { return x + y; } // 函數表達式(Function Expression) let mySum = function (x, y) { return x + y; };
// 函數聲明(Function Declaration)方式函數的類型
function sum(x: number, y: number): number { return x + y; }
//如果要我們現在寫一個對函數表達式(Function Expression)的定義,可能會寫成這樣:
let mySum = function (x: number, y: number): number { return x + y; };
//這是可以通過編譯的,不過事實上,上面的代碼只對等號右側的匿名函數進行了類型定義,而等號左邊的mySum
,是通過賦值操作進行類型推論而推斷出來的。
//如果需要我們手動給mySum
添加類型,則應該是這樣:
let mySum: (x: number, y: number) => number = function (x: number, y: number): number { return x + y; };
//在 TypeScript 的類型定義中,=>
用來表示函數的定義,左邊是輸入類型,需要用括號括起來,右邊是輸出類型。
//我們也可以使用接口的方式來定義一個函數需要符合的形狀
interface SearchFunc { (source: string, subString: string): boolean; } let mySearch: SearchFunc; mySearch = function(source: string, subString: string) { return source.search(subString) !== -1; }
//采用函數表達式|接口定義函數的方式時,對等號左側進行類型限制,可以保證以后對函數名賦值時保證參數個數、參數類型、返回值類型不變。
//前面提到,輸入多余的(或者少於要求的)參數,是不允許的。那么如何定義可選的參數呢?與接口中的可選屬性類似,我們用?
表示可選的參數
//需要注意的是,可選參數必須接在必需參數后面。換句話說,可選參數后面不允許再出現必需參數了
//在 ES6 中,我們允許給函數的參數添加默認值,TypeScript 會將添加了默認值的參數識別為可選參數
//此時就不受「可選參數必須接在必需參數后面」的限制了
//當可選參數在必需參數前面,傳參數時是沒法忽略第一個參數而直接給lastName傳值的,此時,必須對一個參數賦值undefined,觸發第一個參數等於默認值,null是沒有這個效果的
function buildName(firstName: string = 'Tom', lastName: string) { return firstName + ' ' + lastName; } let tomcat = buildName('Tom', 'Cat'); let cat = buildName(undefined, 'Cat');
//重載
//利用聯合類型,我們可以這么實現:
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(''); } }
//然而這樣有一個缺點,就是不能夠精確的表達,輸入為數字的時候,輸出也應該為數字,輸入為字符串的時候,輸出也應該為字符串。這時,我們可以使用重載定義多個 reverse
的函數類型:
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(''); } }
//上例中,我們重復定義了多次函數 reverse
,前幾次都是函數定義,最后一次是函數實現。在編輯器的代碼提示中,可以正確的看到前兩個提示。
//注意,TypeScript 會優先從最前面的函數定義開始匹配,所以多個函數定義如果有包含關系,需要優先把精確的定義寫在前面。