# Essential TypeScript Ch8 Function ## 定義函式 ### 重複定義 ```typescript function calculateTax(amount) { return amount * 1.2; } function calculateTax(amount, discount) { return calculateTax(amount) - discount; } ``` JS不支援函式多載,後面會覆蓋前面 第一個定義被忽略了,呼叫的是第二個 ### 合併函式 ```typescript function calculateTax(amount, discount) { return (amount * 1.2) - discount; } let taxValue = calculateTax(100, 0); // => 120 ``` ### 參數數量 ```typescript let taxValue = calculateTax(100); // 太少 let taxValue = calculateTax(100, 0, 1); // 太多 ``` ### 選擇性參數 ```typescript function calculateTax(amount, discount?) { return (amount * 1.2) - (discount || 0); } // 必須放在後面 let taxValue = calculateTax(100); // discount = undefined let taxValue = calculateTax(100, 10); // discount = 10 ``` ### 預設參數 ```js function calculateTax(amount, discount = 0) { return (amount * 1.2) - discount; } let taxValue = calculateTax(100); // discount = 0 let taxValue = calculateTax(100, 10); // discount = 10 ``` ### 其餘參數 Rest Parameter ```js function calculateTax(amount, discount = 0, ...extraFees) { return (amount * 1.2) - discount + extraFees.reduce((total, val) => total + val, 0); } // typeof extraFees == Array let taxValue = calculateTax(100, 20, 9, 8); // taxValue = 117 ``` ### 參數套用型別註記 - TS預設所有參數為any型別 - 使用註記來宣告成特定型別 ```typescript function calculateTax(amount: number, discount: number = 0, ...extraFees: number[]) { return (amount * 1.2) - discount + extraFees.reduce((total, val) => total + val, 0); } function calculateTax(amount: number, discount?: number, ...extraFees: number[]) { return (amount * 1.2) - discount + extraFees.reduce((total, val) => total + val, 0); } // 寫在參數後面, 預設值前面 let taxValue = calculateTax(100, 20, 9, 8); // taxValue = 117 ``` ### 控制null參數 ```typescript let taxValue = calculateTax(null, 20); // taxValue = -20 /* null被乘法強制轉型為0, 結果也為0 null被系統吃掉了, 或許合理但難以除錯 "strictNullChecks": true (禁止將null, undefined指派給所有型別) */ ``` ### 讓參數接受null ```typescript function calculateTax(amount: number | null, discount: number = 0, ...extraFees: number[]) { if (amount != null) { return (amount * 1.2) - discount + extraFees.reduce((total, val) => total + val, 0); } } let taxValue = calculateTax(null, 0); // taxValue = undefined /* 可以接受null傳入 但最後會得到undefined (Implicit Return) */ ``` ### 自動推論傳回值的型別 ```typescript= // "declaration": true, declare function calculateTax(amount: number | null, discount?: number, ...extraFees: number[]): number | undefined; declare let taxValue: number | undefined; ``` ### 禁止隱性傳回值Implicit Return ```typescript function calculateTax(amount: number | null, discount: number = 0, ...extraFees: number[]) { if (amount != null) { return (amount * 1.2) - discount + extraFees.reduce((total, val) => total + val, 0); } return undefined } let taxValue = calculateTax(null, 0); // taxValue = undefined /* 沒有明確的return傳回值就會提出警告 "noImplicitReturns": true */ ``` ### 傳回值使用型別註記 ```typescript function calculateTax(amount: number, discount: number = 0, ...extraFees: number[]): number { return (amount * 1.2) - discount + extraFees.reduce((total, val) => total + val, 0); } let taxValue = calculateTax(100, 0); // taxValue = 120 let taxValue = calculateTax(null, 0); // Argument of type 'null' is not assignable to parameter of type 'number'. ``` ### 定義void傳回值 ```typescript function calculateTax(amount: number, discount: number = 0, ...extraFees: number[]): number { return (amount * 1.2) - discount + extraFees.reduce((total, val) => total + val, 0); } function writeValue(label: string, value: number): void { console.log(label + ': ' + value); } let taxValue = calculateTax(100, 0); // taxValue = 120 writeValue("Tax value", calculatetax(100, 0)); // writeValue() 不會產生傳回值 => void型別 // 用了return會提出警告 ``` ### 型別多載Type Overloading ```typescript function calculateTax(amount: number): number; function calculateTax(amount: null) null; function calculateTax(amount: number | null): number | null { if (amount != null) { return amount * 1.2; } return null; } function writeValue(label: string, value: number): void { console.log(label + ': ' + value); } let taxValue: number = calculateTax(100); // taxValue = 120 // 接收number型別傳回值 可以直接使用 writeValue("Tax value", taxValue); // => Tax value: 120 ``` ### *條件型別 ```typescript= type taxType<T extends boolean> = T extends true ? number : null let taxValue: taxType<true> = calculateTax(100); let taxValue: taxType<false> = calculateTax(null); ```