TypeScript教程
不解的地方:
ts函數(shù)的重載
ts函數(shù)的接口形式揉忘,看例子不太懂
typescript有兩周類型的數(shù)據(jù):原始數(shù)據(jù)和對象數(shù)據(jù)
原始數(shù)據(jù)類型包括:布爾值卑雁、數(shù)值、字符串贮尉、null
、undefined
以及 ES6 中的新類型 Symbol
。
這里就較為特殊的布爾值莹汤,空值作簡單介紹。
布爾值
布爾值是最基礎的數(shù)據(jù)類型颠印,在 TypeScript 中纲岭,使用 boolean 定義布爾值類型:
let isDone: boolean = false;
// 編譯成功
注意抹竹,使用構造函數(shù) Boolean 創(chuàng)造的對象不是布爾值:
let createdByNewBoolean: boolean = new Boolean(1);
// index.ts(1,5): error TS2322: Type 'Boolean' is not assignable to type 'boolean'
直接調用 Boolean 也可以返回一個 boolean 類型:
let createdByBoolean: boolean = Boolean(1);
?
空值
JavaScript 沒有空值(Void)的概念止潮,
//在 TypeScript 中窃判,可以用 void 表示沒有返回值的函數(shù):
function alertName(): void {
alert('My name is Tom');
}
聲明一個 void 類型的變量沒有什么用,因為你只能將它賦值為 undefined 和 null:
let unusable: void = undefined;
任意值
任意值(Any)用來表示允許賦值為任意類型喇闸。
什么是任意值類型
如果是一個普通類型袄琳,在賦值過程中改變類型是不被允許的:
let myFavoriteNumber: string = 'seven';myFavoriteNumber = 7;
// index.ts(2,1): error TS2322: Type 'number' is not assignable to type 'string'.
但如果是 any
類型,則允許被賦值為任意類型仅偎。
let myFavoriteNumber: any = 'seven';myFavoriteNumber = 7;
任意值的屬性和方法
在任意值上訪問任何屬性都是允許的:
let anyThing: any = 'hello';console.log(anyThing.myName);console.log(anyThing.myName.firstName);
也允許調用任何方法:
let anyThing: any = 'Tom';anyThing.setName('Jerry');anyThing.setName('Jerry').sayHello();anyThing.myName.setFirstName('Cat');
可以認為跨蟹,聲明一個變量為任意值之后,對它的任何操作橘沥,返回的內容的類型都是任意值窗轩。
未聲明類型的變量
變量如果在聲明的時候,未指定其類型座咆,那么它會被識別為任意值類型:
let something;something = 'seven';something = 7;something.setName('Tom');
等價于
let something: any;something = 'seven';something = 7;something.setName('Tom');
什么是類型推論
以下代碼雖然沒有指定類型痢艺,但是會在編譯的時候報錯:
let myFavoriteNumber = 'seven';myFavoriteNumber = 7;
// index.ts(2,1): error TS2322: Type 'number' is not assignable to type 'string'.
事實上,它等價于:
let myFavoriteNumber: string = 'seven';myFavoriteNumber = 7;
// index.ts(2,1): error TS2322: Type 'number' is not assignable to type 'string'.
TypeScript 會在沒有明確的指定類型的時候推測出一個類型介陶,這就是類型推論堤舒。
聯(lián)合類型
let myFavoriteNumber: string | number;myFavoriteNumber = 'seven';myFavoriteNumber = 7;
let myFavoriteNumber: string | number;myFavoriteNumber = true;
// index.ts(2,1): error TS2322: Type 'boolean' is not assignable to type 'string | number'.// Type 'boolean' is not assignable to type 'number'.
聯(lián)合類型使用 |
分隔每個類型。
這里的 let myFavoriteNumber: string | number
的含義是哺呜,允許 myFavoriteNumber
的類型是 string
或者 number
舌缤,但是不能是其他類型。
訪問聯(lián)合類型的屬性或方法
訪問聯(lián)合類型的屬性,只能訪問共有屬性;或者等待數(shù)據(jù)類型確定后,訪問對應的屬性,看不懂看下面例子
當 TypeScript 不確定一個聯(lián)合類型的變量到底是哪個類型的時候某残,我們只能訪問此聯(lián)合類型的所有類型里共有的屬性或方法:
function getLength(something: string | number): number { return something.length;}
// index.ts(2,22): error TS2339: Property 'length' does not exist on type 'string | number'.// Property 'length' does not exist on type 'number'.
上例中国撵,length
不是 string
和 number
的共有屬性,所以會報錯玻墅。
訪問 string
和 number
的共有屬性是沒問題的:
function getString(something: string | number): string {
return something.toString();
}
聯(lián)合類型的變量在被賦值的時候介牙,會根據(jù)類型推論的規(guī)則推斷出一個類型:
let myFavoriteNumber: string | number;myFavoriteNumber = 'seven';
console.log(myFavoriteNumber.length);
// 5myFavoriteNumber = 7;console.log(myFavoriteNumber.length); // 編譯時報錯
// index.ts(5,30): error TS2339: Property 'length' does not exist on type 'number'.
上例中,第二行的 myFavoriteNumber
被推斷成了 string
澳厢,訪問它的 length
屬性不會報錯环础。
而第四行的 myFavoriteNumber
被推斷成了 number
,訪問它的 length
屬性時就報錯了剩拢。
接口對象
簡單的例子
interface Person {
name: string;
age: number;
}
let tom: Person = {
name: 'Tom',
age: 25
};
接口首字母大寫
復雜例子
interface Person {
readonly id: number; //readonly修飾id线得,表示id只讀,在第一次給對象Person賦值時候開始徐伐,id就不在允許賦值
name: string;
age?: number; // 框都?表示可選,表示age可以賦值也可以不
[propName: string]: any; // propName: string表示屬性名是string類型,注意:接口中的所有屬性的類型必須是:后面的子集
}
let tom: Person = {
id: 89757,
name: 'Tom',
gender: 'male'
};
tom.id = 9527; // 報錯魏保,因為對tom的id進行第二次賦值了
TypeScript中不同方式表示數(shù)組
類型+[]
let fibonacci: number[] = [1, 1, 2, 3, 5];
Array<泛型>
let fibonacci: Array<number> = [1, 1, 2, 3, 5];
接口形式表示數(shù)組
interface NumberArray {
[index: number]: number;
}
let fibonacci: NumberArray = [1,1,2,3,]
any在數(shù)組中的應用
let arr1: any[] = [1,2,3,'2',{'i am jxy'}]
ts函數(shù)
聲明函數(shù)
function sum(x: number, y: number): number {
return x + y;
}
函數(shù)的兩種表達方式
表達式
let mySum: (x:number, y:number) =>number =function(x:number, y:number):number{ return x+y ; } // =>的左邊()中的是輸入類型熬尺,右邊()中的是輸出類型
接口形式(不解)
interface SearchFunc{ (source:string, subString: string): boolean; } let mySearch: SearchFunc; mySearch = function(source:string, subString:string){ return source.search(subString) !== -1; }
ts函數(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ù)了:
// **下面例子是錯誤實例,可選參數(shù)必須放在最后i菰邸揭措!**
function buildName(firstName?: string, lastName: string) {
if (firstName) {
return firstName + ' ' + lastName;
} else {
return lastName;
}
}
let tomcat = buildName('Tom', 'Cat');
let tom = buildName(undefined, 'Tom');
參數(shù)默認值
TypeScript 會將添加了默認值的參數(shù)識別為可選參數(shù):
function buildName(firstName: string, lastName: string = 'Cat') {
return firstName + ' ' + lastName;
}
let tomcat = buildName('Tom', 'Cat');
let tom = buildName('Tom');
此時就不受「可選參數(shù)必須接在必需參數(shù)后面」的限制了
剩余參數(shù)
ES6 中,可以使用 ...rest
的方式獲取函數(shù)中的剩余參數(shù)(rest 參數(shù))
在ts中...rest 可以理解為一個數(shù)組刻蚯。所以我們可以用數(shù)組的類型來定義它:
function push(array: any[], ...items: any[]) {
items.forEach(function(item) {
array.push(item);
});
}
let a = [];
push(a, 1, 2, 3);
重載
重載允許一個函數(shù)接受不同數(shù)量或類型的參數(shù)時绊含,作出不同的處理。
比如炊汹,我們需要實現(xiàn)一個函數(shù) reverse
躬充,輸入數(shù)字 123
的時候,輸出反轉的數(shù)字 321
讨便,輸入字符串 'hello'
的時候充甚,輸出反轉的字符串 '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('');
}
}
然而這樣有一個缺點伴找,就是不能夠精確的表達,輸入為數(shù)字的時候废菱,輸出也應該為數(shù)字技矮,輸入為字符串的時候,輸出也應該為字符串殊轴。
這時穆役,我們可以使用重載定義多個 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('');
}
}
上例中,我們重復定義了多次函數(shù) reverse
梳凛,前幾次都是函數(shù)定義,最后一次是函數(shù)實現(xiàn)梳杏。在編輯器的代碼提示中韧拒,可以正確的看到前兩個提示。
注意十性,TypeScript 會優(yōu)先從最前面的函數(shù)定義開始匹配叛溢,所以多個函數(shù)定義如果有包含關系,需要優(yōu)先把精確的定義寫在前面劲适。