在 TypeScript 中,函式型別用於描述函式的型別,包括函式的參數型別和返回型別。它們是一種強大的工具,用於定義函式的形狀,並確保函式的使用方式是正確的。
我們定義了一個變數 combineValues
,但我們並沒有為它指定型別,因此它的型別默認為 any
。在 TypeScript 中,如果不明確指定型別,則 TypeScript 將變數的型別設置為 any
,這表示它可以存儲任何類型的值。
我們將 add
函式賦值給了 combineValues
變數,這意味著 combineValues
現在引用了 add
函式。
function add(n1: number, n2: number): number {
return n1 + n2;
}
let combineValues;
combineValues = add;
console.log(combineValues(8, 8)); // 16
由於 combineValues
是 any
型別,我們嘗試將 combineValues
作為函式執行,而它實際上現在是一個數字。為了避免這種情況,我們需要明確給 combineValues
指定函式型別。
function add(n1: number, n2: number): number {
return n1 + n2;
}
let combineValues;
combineValues = add;
combineValues = 5;
console.log(combineValues(8, 8));
首先,定義 combineValues
型別為 Function
型別,這清楚地表明我們在這裡儲存的任何東西都必須是函式。
function add(n1: number, n2: number): number {
return n1 + n2;
}
let combineValues: Function;
combineValues = add;
combineValues = 5; // TypeScript 報錯,類型 'number' 不可指派給類型 'Function'
console.log(combineValues(8, 8));
接著,我們嘗試將 printResult
函式也賦值給了 combineValues
變數,可以看到我們沒有得到想要的結果,因為我們在 combineValues
儲存錯誤的函式。
function add(n1: number, n2: number): number {
return n1 + n2;
}
function printResult(num: number): void {
console.log(`結果:${num}`); // 結果:17
}
printResult(add(5, 12));
let combineValues: Function;
combineValues = add; // 通過
combineValues = printResult; // 通過
console.log(combineValues(8, 8)); // 結果:8、undefined
首先,函式型別使用箭頭 =>
來表示,並包括參數型別和返回型別。我們的目標是確保 combineValues
是一個能夠接受兩個數字並返回一個數字的函式。在這種情況下,add
函式完全符合所定義的函式型別,但是 printResult
函式卻不符合這個定義,導致 TypeScript 產生錯誤。
function add(n1: number, n2: number): number {
return n1 + n2;
}
function printResult(num: number): void {
console.log(`結果:${num}`); // 結果:17
}
printResult(add(5, 12));
let combineValues: (a: number, b: number) => number;
combineValues = add; // 通過
combineValues = printResult; // TypeScript 報錯,不符合 combineValues 定義的函式型別
使用 TypeScript 的介面搭配函式使用,這種結合可以稱為函式簽名。介面中的函式簽名用於定義函式的形狀(參數與返回值的型別),然後可以實現這個函式簽名的具體函式。
舉例:
interface Calculator {
(n1: number, n2: number): number;
}
const add: Calculator = (a, b) => a + b;
const subtract: Calculator = (a, b) => a - b;
console.log(add(5, 3)); // 8
console.log(subtract(5, 3)); // 2
與介面的可選屬性類似,我們可以使用 ?
表示可選的參數。這意味著該參數可以在函式調用時省略。
舉例:
function greet(name: string, age?: number): string {
if (age === undefined) {
return `我是${name}`;
} else {
return `我是${name} - 我今年 ${age} 歲`;
}
}
const person1 = greet('肉鬆');
console.log(person1); // 我是肉鬆
const person2 = greet('肉鬆', 18);
console.log(person2); // 我是肉鬆 - 我今年 18 歲
特別注意:可選參數必須接在必需參數後面。換句話說,可選參數後面不允許再出現必需參數。
function greet(age?: number, name: string): string {
if (age === undefined) {
return `我是${name}`;
} else {
return `我是${name} - 我今年${age}歲`;
}
}
// TypeScript 報錯,必要參數不得接在選擇性參數之後
當我們希望在函式的參數中設置預設值時,可以使用 TypeScript 的預設參數(Default Parameters)功能。這使得在呼叫函式時,如果未提供特定參數的值,將使用預設值。
舉例:
function greet(name: string = 'Guest'): string {
return `你好,${name}`;
}
const person1 = greet();
console.log(person1); // 你好,Guest
const person2 = greet('肉鬆');
console.log(person2); // 你好,肉鬆
在 TypeScript 中,可以使用剩餘參數(Rest Parameters)來處理函式中不定數量的參數。剩餘參數允許我們在函式中接受一個變數數量的參數,這些參數將被收集到一個陣列中。
舉例:
function sum(...rest: number[]): number {
return rest.reduce((acc, cur) => acc + cur, 0);
}
console.log(sum(1, 2, 3)); // 6
console.log(sum()); // 0,當沒有參數時也可以正常運行
特別注意:剩餘參數必須在函式參數列表的最後。
function sum(...rest: number[], n1: number, n2: number): number {
return rest.reduce((acc, cur) => acc + cur, 0);
}
// TypeScript 報錯,剩餘參數必須是參數清單中的最後一個參數
TypeScript 允許我們定義多個具有不同參數數量和型別的函式型別,這稱為函式重載。這在處理不同的輸入情況時非常有用。
舉例:
function greet(name: string): void;
function greet(name: string, age: number): void;
function greet(name: string, age?: number): void {
if (age === undefined) {
console.log(`Name: ${name}`);
} else {
console.log(`Name: ${name}, Age: ${age}`);
}
}
greet('肉鬆'); // Name: 肉鬆
greet('傑尼龜', 30); // Name: 傑尼龜, Age: 30
=>
符號。?
表示可選的參數,可選參數後面不允許再出現必需參數。