數(shù)組類型
在 TypeScript 中察绷,數(shù)組類型有多種定義方式干签,比較靈活。
-
「類型 + 方括號」表示法
number[]
最簡單的方法是使用「類型 + 方括號」來表示數(shù)組:
let fibonacci: number[] = [1, 1, 2, 3, 5];
數(shù)組的項中不允許出現(xiàn)其他的類型:
//報錯
let fibonacci: number[] = [1, '1', 2, 3, 5];
數(shù)組的一些方法的參數(shù)也會根據(jù)數(shù)組在定義時約定的類型進(jìn)行限制:
let fibonacci: number[] = [1, 1, 2, 3, 5];
fibonacci.push('8'); //報錯
上例中拆撼,push 方法只允許傳入 number 類型的參數(shù)容劳,但是卻傳了一個 string 類型的參數(shù),所以報錯了闸度。
-
數(shù)組泛型
Array<number>
也可以使用數(shù)組泛型(Array Generic) Array<elemType> 來表示數(shù)組:
let fibonacci: Array<number> = [1, 1, 2, 3, 5];
-
用接口表示數(shù)組
[index:number]:number
interface NumberArray {
[index: number]: number;
}
let fibonacci: NumberArray = [1, 1, 2, 3, 5];
-
any 在數(shù)組中的應(yīng)用
一個比較常見的做法是竭贩,用 any 表示數(shù)組中允許出現(xiàn)任意類型:
let list: any[] = ['Xcat Liu', 25, { website: 'http://xcatliu.com' }];
函數(shù)類型
在 JavaScript 中,有兩種常見的定義函數(shù)的方式——函數(shù)聲明(Function Declaration)和函數(shù)表達(dá)式(Function Expression):
// 函數(shù)聲明(Function Declaration)
function sum(x, y) {
return x + y;
}
// 函數(shù)表達(dá)式(Function Expression)
let mySum = function (x, y) {
return x + y;
};
一個函數(shù)有輸入和輸出莺禁,要在 TypeScript 中對其進(jìn)行約束留量,需要把輸入和輸出都考慮到,其中函數(shù)聲明的類型定義較簡單:
-
聲明函數(shù)
function sum(x: number, y: number): number {
return x + y;
}
注意,輸入多余的(或者少于要求的)參數(shù)楼熄,是不被允許的:
function sum(x: number, y: number): number {
return x + y;
}
sum(1, 2, 3);
// index.ts(4,1): error TS2346: Supplied parameters do not match any signature of call target.
function sum(x: number, y: number): number {
return x + y;
}
sum(1);
// index.ts(4,1): error TS2346: Supplied parameters do not match any signature of call target.
-
函數(shù)表達(dá)式
如果要我們現(xiàn)在寫一個對函數(shù)表達(dá)式(Function Expression)的定義忆绰,可能會寫成這樣:
let mySum = function (x: number, y: number): number {
return x + y;
};
這是可以通過編譯的,不過事實上可岂,上面的代碼只對等號右側(cè)的匿名函數(shù)進(jìn)行了類型定義较木,而等號左邊的 mySum,是通過賦值操作進(jìn)行類型推論而推斷出來的青柄。如果需要我們手動給 mySum 添加類型,則應(yīng)該是這樣:
let mySum: (x: number, y: number) => number = function (x: number, y: number): number {
return x + y;
};
注意不要混淆了 TypeScript 中的 => 和 ES6 中的 =>预侯。
在 TypeScript 的類型定義中致开,=> 用來表示函數(shù)的定義,左邊是輸入類型萎馅,需要用括號括起來双戳,右邊是輸出類型。
-
用接口定義函數(shù)的形狀
我們也可以使用接口的方式來定義一個函數(shù)需要符合的形狀:
interface SearchFunc {
(source: string, subString: string): boolean;
}
let mySearch: SearchFunc;
mySearch = function(source: string, subString: string) {
return source.search(subString) !== -1;
}
-
可選參數(shù)
前面提到糜芳,輸入多余的(或者少于要求的)參數(shù)飒货,是不允許的。那么如何定義可選的參數(shù)呢峭竣?
與接口中的可選屬性類似塘辅,我們用 ?
表示可選的參數(shù):
function buildName(firstName: string, lastName?: string) {
if (lastName) {
return firstName + ' ' + lastName;
} else {
return firstName;
}
}
let tomcat = buildName('Tom', 'Cat');
let tom = buildName('Tom');
需要注意的是,可選參數(shù)必須接在必需參數(shù)后面皆撩。換句話說扣墩,可選參數(shù)后面不允許再出現(xiàn)必須參數(shù)了:
function buildName(firstName?: string, lastName: string) {
if (firstName) {
return firstName + ' ' + lastName;
} else {
return lastName;
}
}
let tomcat = buildName('Tom', 'Cat');
let tom = buildName(undefined, 'Tom');
// index.ts(1,40): error TS1016: A required parameter cannot follow an optional parameter.
-
參數(shù)默認(rèn)值
在 ES6 中,我們允許給函數(shù)的參數(shù)添加默認(rèn)值扛吞,TypeScript 會將添加了默認(rèn)值的參數(shù)識別為可選參數(shù):
function buildName(firstName: string, lastName: string = 'Cat') {
return firstName + ' ' + lastName;
}
let tomcat = buildName('Tom', 'Cat');
let tom = buildName('Tom');
此時就不受「可選參數(shù)必須接在必需參數(shù)后面」的限制了:
function buildName(firstName: string = 'Tom', lastName: string) {
return firstName + ' ' + lastName;
}
let tomcat = buildName('Tom', 'Cat');
let cat = buildName(undefined, 'Cat');
關(guān)于默認(rèn)參數(shù)呻惕,可以參考 ES6 中函數(shù)參數(shù)的默認(rèn)值。
-
剩余參數(shù)
ES6 中滥比,可以使用 ...rest 的方式獲取函數(shù)中的剩余參數(shù)(rest 參數(shù)):
function push(array, ...items) {
items.forEach(function(item) {
array.push(item);
});
}
let a = [];
push(a, 1, 2, 3);
事實上亚脆,items 是一個數(shù)組。所以我們可以用數(shù)組的類型來定義它:
function push(array: any[], ...items: any[]) {
items.forEach(function(item) {
array.push(item);
});
}
let a = [];
push(a, 1, 2, 3);
注意盲泛,rest 參數(shù)只能是最后一個參數(shù)濒持,關(guān)于 rest 參數(shù),可以參考 ES6 中的 rest 參數(shù)寺滚。
// 報錯
function f(a, ...b, c) {
// ...
}
-
重載
重載允許一個函數(shù)接受不同數(shù)量或類型的參數(shù)時弥喉,作出不同的處理。
比如玛迄,我們需要實現(xiàn)一個函數(shù) reverse由境,輸入數(shù)字 123 的時候,輸出反轉(zhuǎn)的數(shù)字 321,輸入字符串 'hello' 的時候虏杰,輸出反轉(zhuǎn)的字符串 'olleh'讥蟆。
利用聯(lián)合類型,我們可以這么實現(xiàn):
function reverse(x: number | string): number | string {
if (typeof x === 'number') {
return Number(x.toString().split('').reverse().join(''));
} else if (typeof x === 'string') {
return x.split('').reverse().join('');
}
}
然而這樣有一個缺點纺阔,就是不能夠精確的表達(dá)瘸彤,輸入為數(shù)字的時候,輸出也應(yīng)該為數(shù)字笛钝,輸入為字符串的時候质况,輸出也應(yīng)該為字符串。
這時玻靡,我們可以使用重載定義多個 reverse 的函數(shù)類型:
function reverse(x: number): number;
function reverse(x: string): string;
function reverse(x: number | string): number | string {
if (typeof x === 'number') {
return Number(x.toString().split('').reverse().join(''));
} else if (typeof x === 'string') {
return x.split('').reverse().join('');
}
}
上例中结榄,我們重復(fù)定義了多次函數(shù) reverse,前幾次都是函數(shù)定義囤捻,最后一次是函數(shù)實現(xiàn)臼朗。在編輯器的代碼提示中,可以正確的看到前兩個提示蝎土。
注意视哑,TypeScript 會優(yōu)先從最前面的函數(shù)定義開始匹配,所以多個函數(shù)定義如果有包含關(guān)系誊涯,需要優(yōu)先把精確的定義寫在前面挡毅。