welcome to Cheeto's blog

0%

TypeScript 從零開始:函式型別

TypeScript 從零開始:函式型別

TypeScript 是 JavaScript 的超集合,將強型別帶入 JavaSript,並提供對 ES6 的支援,而 TypeScript 由 Microsoft 開發,程式開源於 GitHub 上。

學習資源參考 TypeScript 新手指南

函式型別

這個章節主要會介紹到函式表達式函式陳述式在 TS 當中是如何定義。

  • 函式陳述式:
1
2
3
4
5
6
7
8
9
10
11
12
// 編譯前
function func1(num1: number, num2: number): number {
return num1 + num2;
}

console.log(func1(2, 2));

// 編譯後
function func1(num1, num2) {
return num1 + num2;
}
console.log(func1(2, 2)); // 4

首先要說參數裡面可以定義型別,那 func1(...): number 後面的這個 number 就是定義回傳值的型別。

  • 函式表達式:
1
2
3
4
5
6
7
8
9
10
11
12
// 編譯前: 可以有兩種寫法
const func1 = (num1: number, num2: number): number => num1 + num2;
const func2: (num1: number, num2: number) => number = (num1, num2) => num1 + num2;

console.log(func1(2, 2));
console.log(func2(4, 4));

// 編譯後
var func1 = function (num1, num2) { return num1 + num2; };
var func2 = function (num1, num2) { return num1 + num2; };
console.log(func1(2, 2)); // 4
console.log(func2(4, 4)); // 8

可選參數

如果定義兩個參數就必須使用兩個,不能只使用一個。

1
2
3
4
const func1 = (num1: number, num2: number): number => num1;
console.log(func1(2));

// 會報錯:An argument for 'num2' was not provided.

那如果想要只用一個參數的話就可以設定可選參數啦!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 編譯前
const func1 = (num1: number, num2?: number) => {
if (num2) {
return num1 + num2;
} else {
return num1;
}
}
func1(2)

// 編譯後
var func1 = function (num1, num2) {
if (num2) {
return num1 + num2;
}
else {
return num1;
}
};
func1(2); // 2

這樣就知道可選參數如何設定了吧?

如何從 interface 中定義函式

1
2
3
4
5
6
7
8
9
10
// 編譯前
interface FuncTS {
(num1: number, num2: number): number
}
const func1: FuncTS = (x, y) => x + y;
func1(5, 4);

// 編譯後
var func1 = function (x, y) { return x + y; };
func1(5, 4);

預設參數

在 ES6 之後有了預設參數,在 TS 當中當然也會有啦!

1
2
3
4
5
const animals = (type: string = '狗', color: string = '黑色', size: string = '大型') => {
return `這隻${ type }毛色是 ${ color },體型是 ${ size }`
}

animals('小貓', '灰色')

方法就跟 ES6 一樣,只要在後面加一個 = 就搞定啦!

其餘參數

在 ES6 之後多了...運算子,那我們要如何在 TS 當中使用呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 編譯前
function func1(name: string, ...nums: number[]) {
console.log(name, nums)
}
func1('Cheeto', 1, 2, 3, 4, 5)

// 編譯後
function func1(name) {
var nums = [];
for (var _i = 1; _i < arguments.length; _i++) {
nums[_i - 1] = arguments[_i];
}
console.log(name, nums);
}
func1('Cheeto', 1, 2, 3, 4, 5); // Cheeto [1, 2, 3, 4, 5]

在這邊有一個小重點必須牢記,其餘參數是陣列,所以在型別定義時必須是陣列唷!

函式型別也能使用聯合型別

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 編譯前
function reverse(item: number | string): number | string {
if (typeof item === 'number') {
return item.toString().split('').reverse().join('');
} else {
return item.split('').reverse().join('');
}
}
reverse('Cheeto')

// 編譯後
function reverse(item) {
if (typeof item === 'number') {
return item.toString().split('').reverse().join('');
}
else {
return item.split('').reverse().join('');
}
}
reverse('Cheeto'); // 回傳 oteehC

又學到了一課 ^^~

型別斷言

當 TS 不能確定一個聯合型別的變數到底是哪個型別的時候,我們可以利用型別斷言告訴 TS。


1
2
3
4
5
6
7
8
9
10
function getLen(item: number | string): number {
// TS 沒辦法分辨參數是 number 還是 string,所以不能確定能不能取到 length,導致報錯
if (item.length) {
return item.length
} else {
return item.toString.length;
}
}

// 會報錯:Property 'length' does not exist on type 'number'.

像這種時候就可以透過型別斷言來告訴 TS,我可以確定這個是 string

1
2
3
4
5
6
7
function getLen(item: number | string): number {
if ((<string>item).length) {
return (<string>item).length;
} else {
return item.toString.length;
}
}

意思就是只有 string 的型別能取到 length,所以你可以透過型別斷言來告訴 TS 我確定這個是 string