# 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);
```